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();
}
}