java的特点
- 面对对象编程(OOP):封装,继承,多态。
https://www.cnblogs.com/chenssy/p/3372798.html
https://www.cnblogs.com/crane-practice/p/3671074.html
==、equals、hashCode
1 、== 对于基本类型来说,比较的是值是否相等;对于引用类型来说,比较的是是否同一个对象。对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。
2、equal 是Object中的方法,等效于"==",比较是否是同一个对象;String类复写了Object的equal方法,比较的是对象的内容。
3、hashCode是Object中的方法,返回一个int类型的hash码,大概可以认为是对象的内存地址。
4、equal()和hashCode()作用一样,都是比较是否是同一个对象,那么比较对象是否相同时只用equal()或者只用hashCode()不就行了,为什么要一起用?
理由:equal比较效率太低,hashCode比较不完全可靠,所以需要结合起来。
详细解释:
(1)重写的equal()里一般比较的比较全面比较复杂,这样效率就比较低,而利用hashCode()进行对比,则只要生成一个hash值进行比较就可以了,效率很高。
(2)Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?
这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。
(3)hashCode()并不是完全可靠,有时候不同的对象他们生成的hashcode也会一样(生成hash值得公式可能存在的问题),所以hashCode()只能说是大部分时候可靠,并不是绝对可靠,所以我们可以得出:equal()相等的两个对象他们的hashCode()肯定相等,也就是用equal()对比是绝对可靠的;hashCode()相等的两个对象他们的equal()不一定相等,也就是hashCode()不是绝对可靠的。
(4)所以,对于需要大量并且快速的对比的话如果都用equal()去做显然效率太低,所以解决方式是,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了,这样既能大大提高了效率也保证了对比的绝对正确性!
https://www.cnblogs.com/kexianting/p/8508207.html
https://www.cnblogs.com/keyi/p/7119825.html
什么是多态?多态的实现机制是什么?
- 多态分为编译时多态和运行时多态,编译时多态指的时方法的重载,即方法名相同,参数不同;运行时多态指的是方法的重写。
运行时多态:父类引用指向子类对象,并调用子类的重写方法。 - 多态实现的机制是什么呢?
其实就是依靠静态分派和动态分派。
静态分派即在编译期间就能完全确定,在类加载的解析阶段就会把所涉及的符号引用转化为可确定的直接引用,不会延迟到运行期再去完成,典型的例子就是方法重载。
动态分派是指在运行期间才能确定变量的实际类型,典型的例子就是方法的重写。只有在运行期间,根据对实例化子类的不同,调用不同子类中重写的方法。
https://blog.csdn.net/ns_code/article/details/17965867
https://blog.csdn.net/sunxianghuang/article/details/52280002
静态属性和静态方法是否可以被继承?是否可以被重写?以及原因?
不存在静态方法的重写,当一个子类继承父类时,写同样的方法时,只是将父类的静态方法隐藏。
理由:静态方法对应的invokestatic,它所需要的符号引用在类加载阶段符号引用解析成为直接引用了,静态分派。
https://blog.csdn.net/dawn_after_dark/article/details/74357049
https://blog.csdn.net/TyroneRenekton/article/details/68923475
String 相关
- new String("a")创建了几个对象
答案:1个或者2个
new一个字符串时,做了两件事。首先在堆中生成了该字符串对象,然后去看常量池中有没有该字符串,如果有就不管了,没有就往常量池中添加一个。
https://www.jianshu.com/p/d416a074409d - String 为什么设计为不可变对象
- String StringBuffer和StringBuilder的比较:拼接效率、线程安全
str += "c";相当于str = new StringBuilder(str).append("JTZen9").toString();
多了创建StringBuilder对象和toString()方法
https://blog.csdn.net/m0_37589327/article/details/78605268
https://www.cnblogs.com/zyh1994/p/5845632.html
浅拷贝与深拷贝
浅拷贝实现了基本类型的复制,引用类型只拷贝了引用,即2个对象中引用指向同一个对象。
https://www.cnblogs.com/Qian123/p/5710533.html#_label3
final、finally、finally
- final:可以修饰变量,方法,类; 修饰变量时表明这对象的值不可变,你不能为这个变量赋一个新的值,或者这样说:对基本类型而言,你不能改变其数值,对于引用,你不能将其指向一个新的引用(而引用自身是可以改变的)。 修饰方法时表明我们希望把这个方法锁定,以防止任何继承类修改它的含义,这样会确保在继承中,我们的 final 方法的行为不会改变,并且不会被覆盖。使用 final 方法的另一个考虑是效率问题:在 Java 早期的时候,遇到 final 方法,编译器会将此方法调用转为内嵌调用,如此一来以减小方法调用产生的开销。 修饰类的时候表明你不打算继承该类,而且也不允许别人这样做。
finally: 是异常处理中进行收场处理的代码块,比如关闭一个数据库连接,清理一些资源占用的问题。不管有没有异常被捕获,finally 子句中的代码都会被执行。
finalize: finalize 出现的原因在于,我们一定需要进行清理动作。Java 没有用于释放对象的,如同 C++ 里的 delete 调用,的方法,而是使用垃圾回收器(GC)帮助我们释放空间。当垃圾回收器准备释放对象占用的存储空间的时候,将首先调用其 finalize() 方法。
网友评论