[金三银四面试季]Java面向对象高频面试题
Posted 波波烤鸭
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[金三银四面试季]Java面向对象高频面试题相关的知识,希望对你有一定的参考价值。
金三银四正是跳槽涨薪的好时节,波哥给大家整理了很多面试高频的问题,助力大家找到更好的工作哦,点点关注,感谢支持。
面向对象面试题
1.谈谈你对面向对象思想的理解?
面向过程编程(POP):是一种以过程为中心的编程思想
面向对象编程(OOP):相对于面向过程来讲的,面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式
2. 谈谈你对面向对象的特征的理解
封装
即把对象的属性和方法包裹起来, 只能通过约定好的接口实现访问
封装是一种信息隐藏技术,在java中通过关键字private实现封装。
package com.bobo.interview0001.domain;
/**
* 属性+方法
*/
public class User
// 将age设置为私有属性
private int age;
public String name;
/**
* 提供给外界设置age属性的方法
* @param age
*/
public void setAge(int age)
if(age < 0 || age > 120)
System.out.println("age的设置不合法!!!");
age = 0;
this.age = age;
/**
* 提供给外界获取age属性的方法
* @return
*/
public int getAge()
return age;
封装的好处:可以将私有数据和公共数据分离,保护私有数据,提高了程序的安全性!!!
继承
继承是面向对象的最显著的一个特征。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
为什么要继承呢:
-
反映现实的真实关系
-
减少代码冗余
-
对父类的属性和方法进行扩展和重写
继承中,子类不可以选择性的继承父类的东西,而是全部继承父类的属性和方法。其中父类又叫超类或基类,子类又叫派生类。父类是子类的一般化,子类是父类的特化(具体化)。java中不支持多继承,一个类最多只能有一个父类。而在java中多继承是通过接口实现的。
public class Person
private String userName;
private int age;
private String sex;
private String address;
private String idCard;
public void show()
System.out.println("父类中的方法");
public class Doctor extends Person
@Override
public void show()
System.out.println("Doctor ... show");
public class Student extends Person
private String ClassNum;
private String stuNo;
// ....
public void learn()
@Override
public void show()
System.out.println("Student ... show");
多态
Java对象的多种状态,多态主要是基于继承和重写,最终可以实现相同的类型调用相同的方法,结果不相同
public static void main(String[] args)
// 多态的体现
Person p1 = new Student();
p1.show();
Person p2 = new Doctor();
p2.show();
3.介绍下访问权限修饰符
修饰符 | 当前类 | 同 包 | 子 类 | 其他包 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
重点注意protected和default,protected相比较default多了一个不同包下面的子类可见
4. String是基本数据类型吗?
Java中的8个基本数据类型:
- byte
- short
- int
- long
- float
- double
- char
- boolean
String类型显然不在8个基本数据类型之中,String类型是我们讲的引用类型
5. float f=6.6这样写是否正确?
不正确的,6.6默认是双精度类型,将double类型赋值给float类型,属性向下转型,会造成精度丢失
public class Demo01
public static void main(String[] args)
// 小数 默认的是 double类型 双精度类型 向下转型 精度丢失
float f2 = 1.1;
float f = 6.6F;
float f1 = 7.7F;
6 程序题1
short s1 = 1;
s1 = s1 + 1; // 此处需要强制类型转换
有错吗? – 有错
short s1 = 1;
s1 += 1; // s1 = (short) ( s1 + 1 )
有错吗?-- 没有错
7. 程序题2
以下程序的输出结果是:
public static void main(String[] args)
Integer f1=100,f2=100,f3=150,f4=150;
System.out.println(f1==f2);
System.out.println(f3==f4);
输出结果:true,false
原因解释:
IntegerCache中的定义
private static class IntegerCache
static final int low = -128;
static final int high;
static final Integer cache[];
static
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null)
try
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
catch( NumberFormatException nfe)
// If the property cannot be parsed into an int, ignore it.
high = h;
// 创建了一个缓存的数组 长度256
cache = new Integer[(high - low) + 1];
int j = low;
// 循环256次
for(int k = 0; k < cache.length; k++)
// 一次创建 -128 到 127 对应的Integer对象,并保存到数组中
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
private IntegerCache()
valueOf(int)中的源码
public static Integer valueOf(int i)
// 如果 i 在 -128 到 127之间
if (i >= IntegerCache.low && i <= IntegerCache.high)
// 就从缓存的数组中返回之前创建的 Integer对象
return IntegerCache.cache[i + (-IntegerCache.low)];
// 否则创建一个新的Integer对象
return new Integer(i);
提醒:越是貌似简单的面试题,其中的玄机就越多,要求面试者需要相对深厚的功力。
8. &和&&的区别
&:按位与
int a = 5; // 101
int b = 3; // 011
int c = a & b;// 001
逻辑与:都为true结果才为true,左边如果为false,右边表达式还是会运行
&&:短路与:都为true结果才为true,左边如果为false,右边表达式不会运行
public static void main(String[] args)
int a = 5; // 101
int b = 3; // 011
int c = a & b;// 001
System.out.println("c = " + c);
// 逻辑与 & 左右两边都为true 那么结果才为true
// 左边为false,结果为false,但是右边的表达式还是会进行运算
if(a == 0 & a ++ > 0)
System.out.println("------");
System.out.println("a = " + a);
// && 短路与 左边如果为false,那么整体的结果也为false,而且右边的表达式不会运算
if(a == 0 && a ++ > 0)
System.out.println("------");
System.out.println("a = " + a);
String name = null;
// 短路与在实际使用的时候还是很有使用场景的
if(name != null & !name.equals(""))
9. switch可以使用的数据类型
JDK5之前:byte,short,int,char
JDK5之后:Java中引入了枚举类型,枚举类型也可以
JDK7之后:可以使用String,但是long类型一直是不可以的
10. 用最有效的方法计算2乘以8?
2 << 3(左移3位,相当于乘以2的3次方)
11. 构造器是否可以被重写?
构造器不能被继承,因此是不能被重写的,但是我们可以重载构造器
12. 是否可以继承String类?
String类是final类型,所以不可以被继承。
13. 重载和重写的区别
方法的重载和重写都是实现多态的方式, 区别在于前者实现的是编译时的多态性, 而后者实现的是运行时的多态性。
重载:在同一个类中,同名的方法如果有不同的参数列表(参数类型,参数个数,顺序)视为重载
package com.bobo.interview0006;
public class Demo01
public static void main(String[] args)
A a = new A();
a.show1();
a.show1(18);
a.show1("a",18);
a.show1(18,"aaa");
class A
/**
* 方法的重载:在同一个类中 方法名称相同 参数列表不同
*/
public void show1()
public void show1(String name)
public void show1(int a)
public void show1(String name,int a)
public void show1(int a,String name)
重写:发生在父子关系类中,子类重写父类的方法,有相同的返回类型或子类
class B extends A
/**
* 重写,子类重写父类中的方法
*/
@Override
public void show1()
// super.show1();
System.out.println("show1 --- B");
/**
* 重写的返回类型必须相同或者是父类返回类型的子类
* @param n
* @return
*/
@Override
public Integer fun1(Number n)
return 666;
14. 抽象类和接口的区别
- 接口和抽象类都不能实例化
- 抽象类相比于普通类多的限制是可以添加抽象方法
- 接口中只能声明常量和抽象方法且访问修饰符必须都为public,在JDK8之后可以定义default方法和static方法
package com.bobo.interview0007;
public class Demo01
public static void main(String[] args)
/**
* 抽象类
* 不能被实例化
* 可以声明普通的属性和方法
* 还可以定义抽象方法
*/
abstract class A
private int a;
public int b;
public void fun1()
public abstract void fun2();
/**
* 接口
* 不能被实例化
* 属性只能是常量
* 方法只能是抽象方法
* JDK1.8之后可以有 default和static方法
*/
interface B
public final int a = 9;
// public abstract 方法默认的类型 可以不添加
public abstract void show1();
/**
* default方法
*/
public default void fun1()
/**
* 静态方法
*/
public static void fun2()
15. 静态内部类和内部类的区别
静态内部类是被声明为static的内部类,它可以不依赖外部类的实例被实例化,而通常我们的内部类是需要通过外部类的实例才能实例化。
public class OutterClass
/**
* 普通内部类
*/
class InnerClass
public void show()
System.out.println("InnerClass ...");
/**
* 静态内部类
*/
static class StaticInnerClass
public void show()
System.out.println("StaticInnerClass ...");
测试代码
public static void main(String[] args)
// 获取普通内部类对象
OutterClass.InnerClass innerClass = new OutterClass().new InnerClass();
innerClass.show();
// 获取静态内部类对象
OutterClass.StaticInnerClass staticInnerClass = new OutterClass.StaticInnerClass();
staticInnerClass.show();
16. 抽象方法是否可以同时是静态的本地方法及被synchronized修饰?
抽象方法所在的类肯定是抽象类,
-
不能被static修饰,因为静态不能被重写,而抽象方法必须要被子类重写,所以矛盾。
-
不能被native修饰,本地方法是由C代码实现的,而抽象方法没有实现,也是矛盾的
-
不能被synchronized修饰,同步是和方法的实现的细节有关系的,而抽象方法没有具体的实现,也是相互矛盾的
17. 静态变量和实例变量的区别
静态变量:是被static所修饰的变量,也称为类变量,它是属性类对象的,不属于类的任何一个对象。静态变量是对象间共享的
实例变量:数据具体的某个对象,必须要先创建对象,然后通过该对象来访问实例变量,
18.静态方法中是否可以访问普通方法
肯定不可以,静态方法是在类加载阶段就创建的,而普通方法是属性对象的,在类加载阶段还没有对象,所以是矛盾的,静态方法只能访问静态成员,普通方法必须要先创建对象,然后通过对象来调用普通方法。
public class Person
static void show()
// 静态方法中不可以调用 普通方法
// speak();
void speak()
// 普通方法可以调用静态方法
show();
19.如何实现克隆
原型模式 | 说明 |
---|---|
浅克隆 | 只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝, 还是指向原生对象的内部元素地址 |
深度克隆 | 深复制把要复制的对象所引用的对象都复制了一遍 |
package com.dpb.prototype;
import java.io.Serializable;
import java.util.Date;
/**
* 原型类:被克隆的类型
* @author dengp
*
*/
public class User implements Cloneable,Serializable
private String name;
private Date birth;
private int age;
public String getName()
return name;
public void setName(String name)
this.name = name;
public Date getBirth()
return birth;
public void setBirth(Date birth)
this.birth = birth;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
/**
* 实现克隆的方法
*/
public Object clone() throws CloneNotSupportedException
return super.clone();
深度克隆
package com.dpb.prototype;
import java.io.Serializable;
import java.util.Date;
/**
* 原型类:被克隆的类型
* 深度克隆测试
* @author dengp
*
*/
public class User2 implements Cloneable,Serializable
private String name;
private Date birth;
private int age;
public String getName()
return name;
public void setName(String name)
this.name = name;
public Date getBirth()
return birth;
public void setBirth(Date birth)
this.birth = birth;
public int getAge()
return age;
public void setAge(int age)
this.age = age;
/**
* 实现克隆的方法
* 深度克隆(deep clone)
*/
public Object clone() throws CloneNotSupportedException
Object object = super.clone();
// 实现深度克隆(deep clone)
User2 user = (User2)object;
user.birth = (Date) this.birth.clone();
return object;
序列化和反序列化
public static void main(String[] args) throws CloneNotSupportedException, Exception
Date date = new Date(1231231231231l);
User user = new User();
user.setName("波波烤鸭");
user.setAge(18);
user.setBirth(date);
System.out.println("-----原型对象的属性------");
System.out.println(user);
System.out.println(user.getName());
System.out.println(user.getBirth());
//使用序列化和反序列化实现深复制
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(user);
byte[] bytes = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectI以上是关于[金三银四面试季]Java面向对象高频面试题的主要内容,如果未能解决你的问题,请参考以下文章
金三银四已过,为大家整理一批高频java面试题,花点耐心看完,offer拿到手软!