1、若对一个类不重写,它的equals()方法是如何比较的?
比较的是对象的地址
2、请解释hashCode()和equals()方法有什么联系?
(1)相等或者相同的对象必须具有相等的哈希码(或者散列码)
(2)如果不重写Object中的hashCode方法,那么hashCode为堆中的内存地址,hashCode是不相同的;但是如果重写了此方法,通过算法计算出来的两个对象的hashCode可能相同,两个对象的值不一定相同
(3)Object的hashCode默认返回的是内存地址,但是hashCode方法可以被重写,所以hashCode不能代表内存地址不同,System.identityHashCode(obj)
可以返回对象的内存地址,不管hashCode方法有没有重写
3、请解释Java中的概念,什么是构造函数?什么是构造函数重载?什么是复制构造函数?
(1)当一个对象被创建时,构造函数会被调用。如果没有提供构造函数,Java编译器会为这个类创建一个默认的无参构造器
(2)构造函数重载与方法重载类似,一个类可以创建多个构造函数,每一个构造函数必须有它唯一的形参列表
(3)Java中没有复制构造函数这个概念
4、请说明Java中的方法覆盖(Overriding)和方法重载(Overloading)是什么意思?
(1)方法覆盖时子类和父类之间才有的,子类继承父类之后,可以重写父类的除了private修饰的方法,重写的方法形参列表相同,返回值相同。子类在实例化的时候会先调用子类的方法,然后调用父类的方法
(2)方法重载是在同一个类中,方法名相同,返回值和形参列表可以不同,但参数列表必须唯一
(3)方法的重载和重写都是实现多态的方式,区别在于重载是编译时多态,重写是运行时多态
5、请说明Query接口的list方法和iterate方法有什么区别?
(1)list()方法无法利用一级缓存和二级缓存,它只能在开启缓存的前提下使用查询缓存;iterate()方法可以充分利用缓存,如果目标数据只读或者频繁读取,则使用iterate()方法会减少开销
(2)list()方法不会引起N+1查询问题,而iterate()方法可能会引起N+1查询问题
6、请你谈一下面向对象的"六原则一法则"。
(1)单一职责原则
(2)开闭原则
(3)依赖倒转原则
(4)里氏代换原则
(5)接口隔离原则
(6)合成聚合复用原则
(7)迪米特法则
7、请说明如何通过反射获取和设置对象私有字段的值?
public class PrivateObject {
private String name = null;
public PrivateObject(String name){
this.name = name;
}
private String getName(){
return this.name;
}
}
8、请说明内部类可以引用他包含类的成员吗,如果可以,有没有什么限制吗?
(1)如果内部类不是静态的,那么它可以访问创建它的外部类对象的所有属性和方法,如果是静态的,那么只能访问创建它的外部类对象的static修饰的属性和方法
(2)当从外部类继承的时候,内部类是不会被覆盖的,他们是完全独立的实体,每个都在自己的命名空间内,如果从内部类中明确的继承,就可以覆盖原来的方法
(3)static的内部类,它可以不依赖于外部类实例被实例化,而非static内部类必须在包含它的外部类实例化之后才能实例化
9、请说明JAVA语言如何进行异常处理,关键字throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
(1)Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每一个异常都是一个对象,它是Throwable类或其它子类的实例
(2)一般情况下在try中执行一段程序,如果出现异常,系统会抛出一个异常,这时候可以根据它的类型在catch中捕捉,finally不管是try还是catch都会执行的一段代码块,throw语句用来明确的抛出一个异常,throws用来标明可能抛出的各种异常,一般用在函数名后面。
(3)在try中可以抛出异常
10、 请判断当一个对象被当作参数传递给一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
是值传递。Java编程语言中只有值传递。当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用,即参数传递的是一个内存地址。对象的内容可以在被调用的方法中改变,但对象的引用是永远都不会改变的
11、请说明Java的接口和抽象类区别。
(1)Java中一个子类只能继承一个抽象类,而接口可以实现多继承
(2)抽象类中既可以有抽象方法,又可以有具体方法;而接口中全是抽象方法
(3)当一个类继承了抽象类之后,必须实现里面所有的抽象方法,可以选择性实现非private的非抽象方法;而当一个类实现了接口,那么就必须实现接口中的所有方法
(4)从设计层面来说,抽象是对类的抽象,是一种模板的设计;接口是行为的抽象,是一种行为的规范
12、请说明一下final, finally, finalize的区别
(1)final用于声明属性、方法、和类,分别表明属性不可变,方法不可覆盖,类不可继承
(2)finally为异常处理语句结构的一部分,表示总是执行,必须配合try才能使用
(3)finalize是Object类中的一个方法,在垃圾回收器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源,比如关闭文件等
13、请你谈谈如何通过反射创建对象?
(1)通过类的
newInstance()
方法,例:String.class.newInstance()
(2)通过类对象的getConstructor()
或getDeclaredConstractor()
方法获取构造器对象,并调用其newInstance()
方法创建对象,例:String.class.getConstructor(String.class).newInstance("hello")
14、请解释一下extends 和super 泛型限定符
总之一句话,编译器可以支持向上转型,但不支持向下转型
上界通配符(List<? extend Fruit>)
(1)表明此list中的对象类型只能是Fruit或者Fruit的子类
(2)上界通配符不能够add除null之外的对象,因为在添加的过程中,list对象无法确定添加的是Fruit还是Fruit的哪一个子类,只能够get
下界通配符(List<? super Apple>)
(1)表明此list中的对象类型只能是Apple或者Apple的父类
(2)下界通配符可以add(向上转型),不能够get,因为在get的时候无法确定取出的对象是Apple还是Apple的父类
15、请你讲讲什么是泛型?
泛型,即“参数化类型”。提到参数,定义方法时有形参,调用此方法时传递实参。参数化类型即将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也可以定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)
16、请你讲讲wait方法的底层原理
(1)
ObjectSynchronizer::wait
方法通过object的对象中找到ObjectMonitor
对象调用方法void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS)
(2)通过ObjectMonitor::AddWaiter
调用把新建立的ObjectWaiter
对象放入到_WaitSet
的队列的末尾中然后在ObjectMonitor::exit
释放锁,接着thread_ParkEvent->park
也就是wait。