Java識別對象方式
- RTTI:編譯時就知道所有類型
- 反射:運行時發現和使用類信息
ps:RTTI工作是由Class對象完成,包含了與類有關的信息。
多態相關概念
讓代碼只操作基類的引用,如果添加新派生類,不會影響原有代碼。
類加載
首先檢查類的class對象是否已加載,如果未加載,就會根據類名查找.class,如果已加載,則接受驗證,以保證其未被破壞。
static代碼塊,在類被加載時運行:1. Class.forName 2. new
Class對象
每個類都有一個Class對象。
Java提供一種方法生產隊Class對象的引用,稱爲類字面常量。可用於普通類、接口、數組、基本數據類型。
在使用.class創建對Class對象的引用時,不會自動初始化該class對象,初始化被延遲到了對靜態方法,或非常數靜態域的首次引用,除非使用Class.forName。
Class引用總指向某個Class對象,它可以創造實例,幷包含作用於這些實例的所有方法代碼。
常用方法
xxx instanceOf XXX:用於判斷類型
Class.newInstance:用於創建對象
Class.isInstance:用於判斷類型
equals和hashCode
- equals
Object的equals是根據地址進行對比,Double、Integer、String等都覆蓋了equals方法,使equals表示爲比較兩元素是否相等。
具有的特點:
- 自反性
- 對稱性
- 傳遞性
- 一致性
- hashCode
方法給對象返回一個hash code值。這個方法被用於hash tables,例如HashMap。
具有的性質:
- 在一個Java應用的執行期間,如果一個對象提供給equals做比較的信息沒有被修改的話,該對象多次調用hashCode()方法,該方法必須始終如一返回同一個integer。
- 如果兩個對象根據equals(Object)方法是相等的,那麼調用二者各自的hashCode()方法必須產生同一個integer結果。
- equals(java.lang.Object)方法不相等的兩個對象,hashCode()方法必須產生不同的integer結果。
- PS: 重點
- equals相等,hashCode也相等。
- 重寫equals時,也需要重寫hashCode。
- hashCode相等,equals不一定相等。、
- 集合中判斷是否相等先判斷hashCode,再判斷equals,重寫hashCode可改變效率。
// String 的hashCode方法
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31 * h + val[off++];
}
hash = h;
}
return h;
}
代理模式的應用
主要介紹java的動態代理,實現InvocationHandler
public interface Service {
// 代理的方法
public abstract void add();
}
public class ServiceImpl implements Service {
public void add() {
System.out.println("This is add service");
}
}
class MyInvocatioHandler implements InvocationHandler {
private Object target;
public MyInvocatioHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("-----before-----");
Object result = method.invoke(target, args);
System.out.println("-----end-----");
return result;
}
}
// 使用動態代理
public class ProxyTest {
public static void main(String[] args) {
Service service = new UserServiceImpl();
// 生成代理對象
MyInvocatioHandler handler = new MyInvocatioHandler(service);
Service serviceProxy = (Service)Proxy.newProxyInstance(Service.class.getClassLoader(), new Class[]{Service.class}, new MyInvocatioHandler(service));
// 使用代理方法
serviceProxy.add();
}
}