**
反射的原理,Class.forName和ClassLoader区别,反射创建类实例的三种方式
Java在编译的时候生成了一个 .class文件,反射就是通过寻找该文件里的字节码找到对应的类、方法、属性。
Class.forName和ClassLoader区别在于前者加载类需要初始化后者不会只是将其加载到了jvm虚拟机中
public class testReflex {
public static void main(String args[]){
Person p1=new Person("小明" ,20,'男' );
Person p2=new Person("小红",22,'女');
//第一种getClass()
Class class1=p1.getClass();
System. out.println(p1.getClass().getName());
try {
Field f=p1.getClass().getDeclaredField("name");
f.setAccessible(true);
f.set(p1, "阿狗");
System. out.println(p1.getName());
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Class class2 = p2.getClass();
System. out.println(class1 == class2 );//true
//第二种利用class属性
Class class3=Person.class;
System. out.println(class1 == class3 );//true
Class class4=null;
try {
//第三种forName()
class4=Class.forName("test.Person");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(class4==class1);//true
}
}
**
**
final的用途
作用于变量若变量为基本类型则不可修改,若变量为引用则可以改变其指向的内容不能改变其指向(即地址不能改地址上存的值能改)
作用于参数与变量一致
作用于方法把方法锁定,以防任何继承类修改它的含义,即该方法不会被继承的类覆盖只能被继承
作用于类该类不可被继承
**
**
Jdk动态代理
jdk动态代理利用反射的机制不过只能代理接口委托类必须实现某个或者某些接口
接口类
package test;
public interface People{
public void sayHello();
}
实现类
package test;
public class Chinese implements People {
@Override
public void sayHello(){
System.out.println("Chinese say hello");
}
}
代理实现类
package test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PeopleInvocationHandler implements InvocationHandler {
private Object people;
PeopleInvocationHandler(Object people){
this.people=people;
}
@Override
public Object invoke(Object proxy,Method method,Object args[])
throws Throwable{
//委托给sun.reflect.MethodAccessor来处理反射
Object invoke=method.invoke(people, args);
System.out.println("---end---");
return invoke;
}
}
测试类
package test;
import java.lang.reflect.Proxy;
public class testproxy {
public static void main(String args[]){
//子类向上转型
People chinese=new Chinese();
PeopleInvocationHandler invohandler=new PeopleInvocationHandler(chinese);
//只能传接口
People proxy= (People)Proxy.newProxyInstance(chinese.getClass().getClassLoader(),chinese.getClass().getInterfaces(),invohandler);
proxy.sayHello();
}
}
Cglib动态代理本质也是通过反射不过是利用继承关系,利用asm在运行时动态生成委托类的子类,从而实现对委托类的代理。因此不依赖接口。所以不能代理final修饰的类
测试类
package test;
public class cglibchinese {
public void sayHello(){
System.out.println("Chinese say hello");
}
public void saysb(){
System.out.println("Chinese say hello sb");
}
}
代理生成类
package test;
import java.lang.reflect.Method;
import java.lang.Object;
import org.springframework.cglib.proxy.*;//用了spring-core-4.xx以上的版本
public class ChineseProxy implements MethodInterceptor{
@Override
public Object intercept(Object object,Method method,Object[] args,MethodProxy methodProxy) throws Throwable{
Object intercept=methodProxy.invokeSuper(object,args);
System.out.println("spcs");
return intercept;
}
}
代理测试类
package test;
import org.springframework.cglib.proxy.*;
public class testcglib {
public static void main(String args[]){
ChineseProxy chineseproxy=new ChineseProxy();
Enhancer enhancer=new Enhancer();
//enhancer.setSuperclass(Chinese.class);
enhancer.setSuperclass(cglibchinese.class);
enhancer.setCallback(chineseproxy);
//People proxy=(People)enhancer.create();代理接口利用向上转型
cglibchinese proxy=(cglibchinese)enhancer.create();
proxy.sayHello();
}
}
**
**
在父类中为子类自动完成所有的 hashcode 和 equals 实现
优点可以添加自定义逻辑,且不必调用超类的实现。
缺点容易出问题尤其是在子类覆盖equals方法没覆盖hashcode时可能降低散列表性能,或者相同对象不同hashcode
**