基础知识汇总
1. == 和 equals的区别:
基本数据类型的比较一般使用==来比较.基本数据类型是:byte short char int long float double boolean
复合数据类型一般使用equals来比较,比较的是他们在内存中的存放地址,所以除非是同一个new出来的对象,否则比较后果为false.
但是String,Integer 和Date这些类型其实是继承并重写了equals方法,并不再是比较其堆内存的内存地址。
java中存在一个字符串缓冲池的概念.每当有一个String对象使用s="test"这样的表达式创建java字符串时,程序首先会去字符串缓冲池中寻找是否存在相同值的对象,如果存在则把这个对象的引用给s而不是重新去创建这样做一个字符串对象。但是,如果是使用 s = new String(“test”)的话则是真正重新创建了另一个字符串对象,这时候s!=s1 但是s.equals(s1)是相等的,因为这时候比较的是字符串的值,而不是两个对象
java.lang.String的intern()方法会去检查字符串缓冲池中是否存在这样一个对象,存在即使使用new String这样的表达式也仍会返回字符串缓冲池中保留的字符串对象。不存在则会往这个字符串缓冲池中加入,再把引用返回去。
2. 对象的hashCode相同时,equals一定相同吗?
Java集合本质是散列表的类,例如HashMap HashTable HashSet等,hashCode只有在散列表中才有用,其他情况下都是无用的。
在普通的类下 hashcode和equals并无任何关系。
在散列表中是有关系的,如果他们的对象相等则他们的hashcode则一定相等。这里指equals相等。
如果两个对象的hashCode相等,他们的类不一定相等。
因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等,并不一定能得出键值对相等。补充说一句:“两个不同的键值对,哈希值相等”,这就是哈希冲突。
在这种情况下。若要判断两个对象是否相等,除了要覆盖equals()之外,也要覆盖hashCode()函数。否则,equals()无效。
例如,创建Person类的HashSet集合,必须同时覆盖Person类的equals() 和 hashCode()方法。
3. final在java中的作用
在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)
1.修饰类时,这个类则不能被继承。而且类中的成员方法会被隐形的指定为final方法
2.修饰方法时,此方法则不能被重写。private方法隐形的被指定为final方法
3.对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
4.引用变量被final修饰之后,虽然不能再指向其他对象,但是它指向的对象的内容是可变的。
4. 编译期和运行期
java从源文件创建到程序的执行需要经过两大步,一步是源代码经过编译器编译为字节码,第二步是由java虚拟机将编译好的字节码解释运行。java语言也被称为半解释的语言。编译后的字节码主要分为两个部分:1.常量池 2.方法字节码 常量池里记录的是代码出现过的类名 成员变量等以及符号引用(方法引用、成员变量引用等等) 方法字节码中则放的是各个方法的字节码。
java中的所有public和protected的实例方法都是采用动态绑定的机制,所有的私有方法、静态方法、构造器和初始化方法都是静态绑定机制。采用动态绑定的方法会用到方法表,静态绑定不会。
方法的重载发生在编译时。在编译过程中,编译器必须根据参数类型以及长度来确定到底是调用的哪个方法,这也是Java编译时多态的体现。
方法的重写发生在运行时。因为在编译时,编译器是无法知道我们到底是调用父类的方法还是子类的方法,相反的,只有在实际运行的时候,我们才知道应该调用哪个方法。这个也是java运行时多态的体现。
5. Math.round(-1.5)是多少
Java的round方法是四舍五入的计算,入的时候是大于他的整数round(x) = floor(x+0.5)
floor是返回不大于的最大整数
ceil这是不小于他的最小整数
System.out.println(Math.round(-1.5));
System.out.println(Math.floor(-1.5));
System.out.println(Math.ceil(-1.5));
最后输出是:
-1
-2.0
-1.0
6. 抽象类和接口的区别
语法上区别:
1.抽象类中可以提供实现的成员方法 但是接口中只能是abstract 方法
2.抽象类中的成员变量可以是各种类型的,但是接口中只能是 public static final的
3.接口中不能含有静态方法和静态代码 但是抽象类中可以有
4.一个类只能继承一个抽象类,但是可以实现多个接口
设计层面上的区别:
1.抽象类是对一种事物的抽象,即对类的抽象。接口是对某些行为的抽象。抽象类是对整个类整体进行抽象,包括属性 行为 但是接口却是对类的部分(行为)进行抽象。
2.抽象类作为很多子类的父类,它是一种模板设计,而接口则是一种行为规范。
比如对一个门来说开门和关门是一个门的固有属性,但是某些门有自有属性。所以可以把门抽象成一个父类,不同的门都可以继承这个抽象类。但是有的门可以有猫眼 可以是报警的功能,可以把这些抽象为一个接口,需要的子类再去实现这些接口
7. 对象的生命周期
对象基本上都是在jvm的堆区中创建,在创建对象之前,会触发类加载(加载、连接、初始化),当类初始化完成后,根据类信息在堆区中实例化类对象,初始化非静态变量、非静态代码以及默认构造方法,当对象使用完之后会在合适的时候被jvm垃圾收集器回收。对象的生命周期只是类的生命周期中使用阶段的主动引用的一种情况(即实例化类对象)。而类的整个生命周期则要比对象的生命周期长的多.
对象的生命周期:
1.创建阶段
2. 应用阶段
3. 不可见阶段
4.不可达阶段
5. 收集阶段
6.终结阶段
7.空间重新分配阶段
1.创建阶段:为对象分配存储空间 开始构造对象 从超类到子类对static成员进行初始化
2.对象至少被一个强引用持有着
3.程序的执行已经超出了对象的作用域
4.不可达是指对象不再被任何强引用所持有
5.收集阶段是已经发现该对象已经处于不可达的阶段并且垃圾回收器已经给对该对象的内存空间重新分配做好准备,则对象进入了收集阶段。如果对象重写了finalize()方法,则会执行该方法
6.不建议重写finazlie方法 因为一旦重载该方法,则在分配该对象时需要在垃圾回收器上注册此对象,以便在回收时能够执行该重载方法;该方法的执行需要消耗CPU时间且该方法执行完毕之后才会再次执行回收操作在重载方法中如果有其他强引用再次持有该对象,则会导致对象的状态由手机阶段变更为引用阶段
7.当对象执行完finalize()后仍处于不可达状态。则该对象进入终结阶段等待GC的回收。
8.GC对该对象的占用的内存空间进行回收和再分配了,对象彻底消失。