第十三章:Java_反射机制
来源:互联网 发布:vivo手机数据恢复软件 编辑:程序博客网 时间:2024/05/20 02:24
反射?
类的加载过程:
1.如何创建Class的实例(重点)
1.1过程:源文件经过编译(javac.exe)以后,得到一个或多个.class文件。.class文件经过运行(java.exe)这步,
就需要进行类的加载(通过JVM的类的加载器),记载到内存中的缓存。每一个放入缓存中的.class文件就是一个Class的实例!
1.2 Class的一个对象,对应着一个运行时类。相当于一个运行时类本身充当了Class的一个实例。
1.3 java.lang.Class是反射的源头。 接下来涉及到反射的类都在java.lang.reflect子包下。如:Field Method Constructor Type Package..
当通过Class的实例调用getMethods() —>Method , getConstructors() —->Constructor
1.4实例化Class的方法(三种):
// 1.调用运行时类的.class属性 Class clazz1 = Person.class; System.out.println(clazz1); Class clazz2 = Creator.class; System.out.println(clazz2); // 2.通过运行时类的对象,调用其getClass()方法 Person p = new Person(); Class clazz3 = p.getClass(); System.out.println(clazz3); // 3.调用Class的静态方法forName(String className)。此方法报ClassNotFoundException String className = "com.atguigu.java.Person"; Class clazz4 = Class.forName(className); System.out.println(clazz4);
2.Class的实例–应用一
应用一:可以创建对应的运行时类的对象(重点)
//获取运行时类的对象:方法一 @Test public void test1() throws Exception{ Class clazz = Class.forName("com.atguigu.review.Animal"); Object obj = clazz.newInstance(); Animal a = (Animal)obj; System.out.println(a); } //调用指定的构造器创建运行时类的对象 @Test public void test2() throws Exception{ Class clazz = Animal.class; Constructor cons = clazz.getDeclaredConstructor(String.class,int.class); cons.setAccessible(true); Animal a = (Animal)cons.newInstance("Tom",10); System.out.println(a); }
3.Class的实例–应用二
应用二:获取对应的运行时类的完整的类的结构:属性、方法、构造器、包、父类、接口、泛型、注解、异常、内部类。。。
如:Method[] m1 = clazz.getMethods() :获取到对应的运行时类中声明的权限为public的方法(包含其父类中的声明的public)
Method[] m2 = clazz.getDeclaredMethods():获取到对应的运行时类中声明的所有的方法(①任何权限修饰符修饰的都能获取②不含父类中的)
4.Class的实例–应用三
应用三:调用对应的运行时类中指定的结构(某个指定的属性、方法、构造器)(重点)
//调用指定属性@Testpublic void test3() throws Exception{ Class clazz = Class.forName("com.atguigu.review.Animal"); Object obj = clazz.newInstance(); Animal a = (Animal)obj; //调用非public的属性 Field f1 = clazz.getDeclaredField("name"); f1.setAccessible(true); f1.set(a, "Jerry"); //调用public的属性 Field f2 = clazz.getField("age"); f2.set(a, 9); System.out.println(f2.get(a)); System.out.println(a); //调用static的属性 Field f3 = clazz.getDeclaredField("desc"); System.out.println(f3.get(null));}//调用指定的方法@Testpublic void test4() throws Exception{ Class clazz = Class.forName("com.atguigu.review.Animal"); Object obj = clazz.newInstance(); Animal a = (Animal)obj; //调用非public的方法 Method m1 = clazz.getDeclaredMethod("getAge"); m1.setAccessible(true); int age = (Integer)m1.invoke(a); System.out.println(age); //调用public的方法 Method m2 = clazz.getMethod("show", String.class); Object returnVal = m2.invoke(a,"金毛"); System.out.println(returnVal); //调用static的方法 Method m3 = clazz.getDeclaredMethod("info"); m3.setAccessible(true);// m3.invoke(Animal.class); m3.invoke(null); }
5.动态代理—反射的应用
体会反射的动态性
代理设计模式的原理:
使用一个代理将对象包装起来, 然后用该代理对象取代原始对象. 任何对原始对象的调用都要通过代理. 代理对象决定是否以及何时
将方法调用转到原始对象上
静态代理:要求被代理类和代理类同时实现相应的一套接口;通过代理类的对象调用重写接口的方法时,实际上执行的是被代理类的同样的
方法的调用。
静态代理模式
//静态代理模式//接口interface ClothFactory { void productCloth();}// 被代理类class NikeColthFactory implements ClothFactory { @Override public void productCloth() { System.out.println("Nike工厂生产了一批衣服"); }}// 代理类class ProxFactory implements ClothFactory { ClothFactory cf; public ProxFactory(ClothFactory cf) { this.cf = cf; } @Override public void productCloth() { System.out.println("代理类开始执行,收代理费$1000"); cf.productCloth(); }}public class TestClothProduct { public static void main(String[] args) { NikeColthFactory nike = new NikeColthFactory();// 创建被代理类的对象 ProxFactory prxoy = new ProxFactory(nike);// 创建代理类的对象 prxoy.productCloth(); }}
动态代理:在程序运行时,根据被代理类及其实现的接口,动态的创建一个代理类。当调用代理类的实现的抽象方法时,就发起对被代理类同样
方法的调用。
涉及到的技术点:①提供一个实现了InvocationHandler接口实现类,并重写其invoke()方法 ②Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),h);
注:obj:被代理类对象 ; h:实现了InvocationHandler接口的实现类的对象
动态代理的使用
//动态代理的使用,体会反射是动态语言的关键interface Subject { void action();}// 被代理类class RealSubject implements Subject { public void action() { System.out.println("我是被代理类,记得要执行我哦!么么~~"); }}class MyInvocationHandler implements InvocationHandler { Object obj;// 实现了接口的被代理类的对象的声明 // ①给被代理的对象实例化②返回一个代理类的对象 public Object blind(Object obj) { this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), this); } //当通过代理类的对象发起对被重写的方法的调用时,都会转换为对如下的invoke方法的调用 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //method方法的返回值时returnVal Object returnVal = method.invoke(obj, args); return returnVal; }}public class TestProxy { public static void main(String[] args) { //1.被代理类的对象 RealSubject real = new RealSubject(); //2.创建一个实现了InvacationHandler接口的类的对象 MyInvocationHandler handler = new MyInvocationHandler(); //3.调用blind()方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象。 Object obj = handler.blind(real); Subject sub = (Subject)obj;//此时sub就是代理类的对象 sub.action();//转到对InvacationHandler接口的实现类的invoke()方法的调用 //再举一例 NikeClothFactory nike = new NikeClothFactory(); ClothFactory proxyCloth = (ClothFactory)handler.blind(nike);//proxyCloth即为代理类的对象 proxyCloth.productCloth(); }}
动态代理与AOP
interface Human { void info(); void fly();}// 被代理类class SuperMan implements Human { public void info() { System.out.println("我是超人!我怕谁!"); } public void fly() { System.out.println("I believe I can fly!"); }}class HumanUtil { public void method1() { System.out.println("=======方法一======="); } public void method2() { System.out.println("=======方法二======="); }}class MyInvocationHandler implements InvocationHandler { Object obj;// 被代理类对象的声明 public void setObject(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { HumanUtil h = new HumanUtil(); h.method1(); Object returnVal = method.invoke(obj, args); h.method2(); return returnVal; }}class MyProxy { // 动态的创建一个代理类的对象 public static Object getProxyInstance(Object obj) { MyInvocationHandler handler = new MyInvocationHandler(); handler.setObject(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj .getClass().getInterfaces(), handler); }}public class TestAOP { public static void main(String[] args) { SuperMan man = new SuperMan();//创建一个被代理类的对象 Object obj = MyProxy.getProxyInstance(man);//返回一个代理类的对象 Human hu = (Human)obj; hu.info();//通过代理类的对象调用重写的抽象方法 System.out.println(); hu.fly(); //********* NikeClothFactory nike = new NikeClothFactory(); Object obj1 = MyProxy.getProxyInstance(nike); ClothFactory cloth = (ClothFactory)obj1; cloth.productCloth(); }}
效果:
反射例子
public class TestReflection { //调用指定的方法 @Test public void test4() throws Exception{ Class clazz = Class.forName("com.atguigu.review.Animal"); Object obj = clazz.newInstance(); Animal a = (Animal)obj; //调用非public的方法 Method m1 = clazz.getDeclaredMethod("getAge"); m1.setAccessible(true); int age = (Integer)m1.invoke(a); System.out.println(age); //调用public的方法 Method m2 = clazz.getMethod("show", String.class); Object returnVal = m2.invoke(a,"金毛"); System.out.println(returnVal); //调用static的方法 Method m3 = clazz.getDeclaredMethod("info"); m3.setAccessible(true);// m3.invoke(Animal.class); m3.invoke(null); } //调用指定属性 @Test public void test3() throws Exception{ Class clazz = Class.forName("com.atguigu.review.Animal"); Object obj = clazz.newInstance(); Animal a = (Animal)obj; //调用非public的属性 Field f1 = clazz.getDeclaredField("name"); f1.setAccessible(true); f1.set(a, "Jerry"); //调用public的属性 Field f2 = clazz.getField("age"); f2.set(a, 9);` System.out.println(f2.get(a)); System.out.println(a); //调用static的属性 Field f3 = clazz.getDeclaredField("desc"); System.out.println(f3.get(null)); } //调用指定的构造器创建运行时类的对象 @Test public void test2() throws Exception{ Class clazz = Animal.class; Constructor cons = clazz.getDeclaredConstructor(String.class,int.class); cons.setAccessible(true); Animal a = (Animal)cons.newInstance("Tom",10); System.out.println(a); } //获取运行时类的对象:方法一 @Test public void test1() throws Exception{ Class clazz = Class.forName("com.atguigu.review.Animal"); Object obj = clazz.newInstance(); Animal a = (Animal)obj; System.out.println(a); }}
如何获取:
public class TestReflection { //关于类的加载器:ClassLoader @Test public void test5() throws Exception{ ClassLoader loader1 = ClassLoader.getSystemClassLoader(); System.out.println(loader1); ClassLoader loader2 = loader1.getParent(); System.out.println(loader2); ClassLoader loader3 = loader2.getParent(); System.out.println(loader3); Class clazz1 = Person.class; ClassLoader loader4 = clazz1.getClassLoader(); System.out.println(loader4); String className = "java.lang.String"; Class clazz2 = Class.forName(className); ClassLoader loader5 = clazz2.getClassLoader(); System.out.println(loader5); //掌握如下 //法一: ClassLoader loader = this.getClass().getClassLoader(); InputStream is = loader.getResourceAsStream("com\\atguigu\\java\\jdbc.properties"); //法二:// FileInputStream is = new FileInputStream(new File("jdbc1.properties")); Properties pros = new Properties(); pros.load(is); String name = pros.getProperty("user"); System.out.println(name); String password = pros.getProperty("password"); System.out.println(password); } //如何获取Class的实例(3种) @Test public void test4() throws ClassNotFoundException{ //1.调用运行时类本身的.class属性 Class clazz1 = Person.class; System.out.println(clazz1.getName()); Class clazz2 = String.class; System.out.println(clazz2.getName()); //2.通过运行时类的对象获取 Person p = new Person(); Class clazz3 = p.getClass(); System.out.println(clazz3.getName()); //3.通过Class的静态方法获取.通过此方式,体会一下,反射的动态性。 String className = "com.atguigu.java.Person"; Class clazz4 = Class.forName(className);// clazz4.newInstance(); System.out.println(clazz4.getName()); //4.(了解)通过类的加载器 ClassLoader classLoader = this.getClass().getClassLoader(); Class clazz5 = classLoader.loadClass(className); System.out.println(clazz5.getName()); System.out.println(clazz1 == clazz3);//true System.out.println(clazz1 == clazz4);//true System.out.println(clazz1 == clazz5);//true } /* * java.lang.Class:是反射的源头。 * 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成的) * 此.class文件,此.class文件加载到内存以后,就是一个运行时类,存在在缓存区。那么这个运行时类本身就是一个Class的实例! * 1.每一个运行时类只加载一次! * 2.有了Class的实例以后,我们才可以进行如下的操作: * 1)*创建对应的运行时类的对象 * 2)获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解、...) * 3)*调用对应的运行时类的指定的结构(属性、方法、构造器) * 4)反射的应用:动态代理 */ @Test public void test3(){ Person p = new Person(); Class clazz = p.getClass();//通过运行时类的对象,调用其getClass(),返回其运行时类。 System.out.println(clazz); } //有了反射,可以通过反射创建一个类的对象,并调用其中的结构 @Test public void test2() throws Exception{ Class clazz = Person.class;// Class clazz1 = String.class; //1.创建clazz对应的运行时类Person类的对象 Person p = (Person)clazz.newInstance(); System.out.println(p); //2.通过反射调用运行时类的指定的属性 //2.1 Field f1 = clazz.getField("name"); f1.set(p,"LiuDeHua"); System.out.println(p); //2.2 Field f2 = clazz.getDeclaredField("age"); f2.setAccessible(true); f2.set(p, 20); System.out.println(p); //3.通过反射调用运行时类的指定的方法 Method m1 = clazz.getMethod("show"); m1.invoke(p); Method m2 = clazz.getMethod("display",String.class); m2.invoke(p,"CHN"); } //在有反射以前,如何创建一个类的对象,并调用其中的方法、属性 @Test public void test1(){ Person p = new Person();// Person p1 = new Person(); p.setAge(10); p.setName("TangWei"); System.out.println(p); p.show();// p.display("HK"); }}
- 第十三章:Java_反射机制
- Java_反射机制
- Java_反射机制
- 第十三章:反射
- Java_反射
- JAVA_反射
- java_反射
- java_反射
- JAVA_反射
- Java_反射
- Java_反射
- java_反射
- [疯狂Java讲义精粹] 第十三章|类加载机制与反射
- java_什么是反射?
- java_反射日记
- Java_反射(reflect)
- 第十三章 类加载和反射
- Java_垃圾回收机制
- 坚持#第143天~努力发展自己的天赋
- linux下配置jdk环境
- 欢迎使用CSDN-markdown编辑器
- Python笔记---setuptools 、feedparser、pydelicious
- 选课时间
- 第十三章:Java_反射机制
- AndroidStudio的代码转至eclipse
- 分享一个短信轰炸机、呼死你软件
- Matrices with XOR property
- 使用git将本地项目上传到github上面
- 【算法】牛客网模拟题编程部分
- USACO
- artTemplate使用笔记
- the parameter of session timeout