Java里面所有的不变的属性需要用final修饰吗
答:没必要。你可以实现相同的功能通过以下操作:
设为非final的private 变量,且只有在构造函数中才能修改。不设set方法,如果是一个可变对象,不要泄露任何指向这个对象的引用。设置一个引用变量为final 只能确保这个变量不会被赋予一个不同的引用,但是你仍然可以改变引用变量的属性值。
String的subString()实现原理
答:substring取原来string的一部分创建一个新的对象。这个问题主要想问substring可能导致的内存泄露风险。
直到Java1.7, substring 拥有原来的字符数组的引用,这意味着即使是五字符这么小的字符串,也可能会导致一个1GB字符数组无法被垃圾回收,因为有一个强引用。
这个问题在Java1.7中已经被修复,原来的字符数组不会被引用,但是会导致创建substring耗时会有点长,以前时间复杂度是 O(1), Java 7之后时间复杂度是 O(n)。
Java中如何处理写存储过程或者读存储过程时遇到的错误
答: 一个存储过程应该在操作错误时返回错误码,但是如果存储过程本身出问题,捕获 SQLException 是唯一选择。
工厂模式和抽象工厂模式有什么区别
答:抽象工场模式提供一个多层级的抽象。考虑不同的工厂继承自同一个抽象工厂,代表基于工厂的不同对象结构的创建,例如, AutomobileFactory,UserFactory,RoleFactory等都继承自 AbstractFactory。每一个独立的工厂代表那种类型物体的创造器。
下面是一个工厂模式和抽象工厂模式的UML图:
什么时候重写 hashCode()和 equals()方法
答:当需要通过业务逻辑校验两个对象是否相等,而不是通过两个对象是否执行同一地址。例如两个员工对象在 emp_id 相等的时候相等,即使它们是通过不同的代码创建出来的两个不同对象。
另外,如果你使用一个对象作为 HashMap的key,你必须重写这两个方法。
作为java equals-hashcode约束的一部分,当你重写equals的时候,必须重写hashcode. 否则你不能在Set,Map这样的类里面使用,因为他们通过equals()方法来保证逻辑正确性。
双引号直接创建字符串和使用new()创建字符串有什么区别
答: 使用new()创建String对象,实例被创建在堆中, 不会被添加到String常量池中,当通过字面量创建时,会被放到堆中的永久区的String常量池中。
Stringstr = newString(“Test”) 不会把str放到String常量池中,需要调用String.intern()方法,才会把它放到String常量池中。
当使用String字面量创建String对象时,如通过String s = “Test”, java会自动放入String常量池中。
另外,如果把”Test”这样的String字面量传进去,也会创建另外一个对象:”Test” 在String常量池。
什么是不可变对象,如何写一个不可变类
答:不可变对象是指Java类的对象一单被创建,不能被修改。任何不可变对象对象的修改在创建时候就已经完成,例如,Java中String是不可变的。
大多数不可变类是final的, 这样可以防止因子类重写方法而导致不可变失效。
你也可以实现相同的功能通过让成员非final但是private,且除了构造方法任何其他方法无法修改。
另外,要确保没有暴露不可变对象的内部,尤其是它包含可变成员的时候。
同时,当你从客户端接收到可变的对象时,例如 java.util.Date, 使用clone() 方法 来获取一个独立的拷贝,防止恶意修改可变对象带来的风险。
相同的优化需要在返回一个可变成员时执行。返回另一个独立拷贝给客户端;不要返回可变对象的原始引用。