< 笔记 > Java SE
来源:互联网 发布:代挂乐最新源码 编辑:程序博客网 时间:2024/05/29 09:30
09 Java SE 反射
By Kevin Song
定义:反射机制是在运行状态中,对于任意一个类(class文件),都能知道这个类的所有方法和属性。对于任意一个对象都能调用它的任意一个方法和属性。
Tomcat例
- Tomcat App提供 Servlet接口
- MyServlet类实现Servlet接口
- 编写MyServlet类配置文件
- Tomcat直接读取配置文件来动态获取MyServlet类中的方法和属性
- Tomcat通过Class类来获取MyServlet类字节码文件中的内容(想要对MyServlet文件进行内容获取,第一步要获取该类的字节码文件对象即可)
- 获取Class类中的对象(字节码文件对象)
- Tomcat通过Class类中的forName()方法获取MyServlet类字节码文件对象
- 获取Class类中的构造方法
- 通过newInstance()获取该类空构造方法对象
- 通过getConstructor获取构造方法对象
- 再通过构造方法对象newInstance();方法来创建非空参对象
- 获取Class类中的字段
- 获取Class类中的方法
- 获取Class类中的对象(字节码文件对象)
- Tomcat通过Class类来获取MyServlet类字节码文件中的内容(想要对MyServlet文件进行内容获取,第一步要获取该类的字节码文件对象即可)
class Person { name; age;}Person p1 = new Person(Leo, 20);Person P2 = new Person(Kylo, 28);
//描述字节码文件的类class Class { 提供可以获取字节码文件的内容(字段,构造方法,一般方法)}class Demo { int a = 6; Demo() {} void show() {}}class Test { int b = 9; Test() {} void abc() {}}
获取Class对象
三种方式
- 方式三:Object类中的getClass()方法
- 必须明确具体的类并且创建对象
- 方式二:任何数据类型都具备一个静态的属性.class来获取其对应的class对象
- 要明确类中的静态成员
- 方式三:通过给定的类的字符串名称就可以获取该类
- Class类中的forName()方法
public class ReflectDemo { public static void main(String[] args) { //方式一:Object类中的getClass()方法 public static void getClassObject_1() { Person p = new Person(); Class clazz = p.getClass(); Person p1 = ne Person(); Class clazz1 = p1.getClass(); System.out.println(clazz==clazz1);//true } //方式二 public static void getClassObject_2() { Class clazz = Person.class; Class clazz1 = Person.class; System.out.println(clazz==clazz1);//true } //方式三 public static void getClassObject_3() throws ClassNotFoundException { String className ="Person"; Class class = Class.forName(className); System.out.println(clazz); } }}public class Person { private int age; private String name; public Person(int age, String name) { super(); this.age = age; this.name = name; System.out.println(personParam run""); } public Person() { super; System.out.println(person run""); } public void show() { System.out.println(name+"..."+age); } private void method() { System.out.println("method run"); } public void paraMethod(String str, int num) { System.out.println("paramMethod run"+str+":"+num); } public static void staticMethod() { System.out.println("staticMethod run"); }}
获取Class中的构造方法
- 早期创建对象
- new的时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内创建该字节码文件对象,然后创建该字节文件的对应Person对象
- 反射创建对象
- 只要知道类名,通过Class来创建该类字节码文件对象
- 通过newInstance()获取该类空构造方法对象
- 通过getConstructor获取构造方法对象
- 再通过构造方法对象newInstance();方法来创建非空参对象
- 只要知道类名,通过Class来创建该类字节码文件对象
public class ReflectDemo2 { public static void main(String[] args) { createNewObject_1(); createNewObject_2(); } //空参数构造方法 public static void createNewObject_1() { //以前 Person p = new Person(); //反射 String name = "Person"; Class clazz = Clazz.forName(name);//获取Person类字节码文件对象 Object obj = clazz.newInstance();//产生Person类对象 } //非空参数构造方法 public static void createNewObject_2() { String name = "Person"; Class clazz = Clazz.forName(name);//获取Person类字节码文件对象 //获取指定构造函数的对象 Constructor constructor = clazz.getConstructor(String.class, int.class); Object obj = constructor.newInstance("Kylo", 29); }}
获取Class中的字段
public class ReflectDemo3 { public static void main(String[] args) { createNewObject_1(); createNewObject_2(); } //空参数构造方法 public static void getFieldDemo() { Class clazz = Class.forName("Person"); Field field = clazz.getField("age");//获取公有的 field = clazz.getDeclaredField("age");//获取本类,包含私有 //对私有字段的访问取消权限检查,强制访问 field.setAccessible(true); Object obj = clazz.newInstance(); field.set(obj,20); Object o = field.get(obj); System.out.println(o); }}
获取Class中的方法
public class ReflectDemo4 { public static void main(String[] args) throws Exception { getMethodDemo_3(); } //获取有参方法 public static void getMethodDemo_3() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); Method method = clazz.getMethod("paramMethod", String.class,int.class); Object obj = clazz.newInstance(); method.invoke(obj, "小强",89); } //获取无参方法 public static void getMethodDemo_2() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); Method method = clazz.getMethod("show", null);//获取空参数一般方法。 //Object obj = clazz.newInstance(); Constructor constructor = clazz.getConstructor(String.class,int.class); Object obj = constructor.newInstance("小明",37); method.invoke(obj, null); } //获取指定Class中的所有公共方法 public static void getMethodDemo() throws Exception { Class clazz = Class.forName("cn.itcast.bean.Person"); Method[] methods = clazz.getMethods();//获取的都是公有的方法。 methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有。 for(Method method : methods){ System.out.println(method); } }}
反射练习
public class Mainboard { public void run() { System.out.println("main board run...."); } public void usePCI(PCI p) {//PCI p = new SouncCard(); if (p != null) { p.open(); p.close(); } }}public class SoundCard implements PCI { public void open(){ System.out.println("sound open"); } public void close(){ System.out.println("sound close"); }}public class NetCard implements PCI { @Override public void open() { System.out.println("net open"); } @Override public void close() { System.out.println("net close"); }}public interface PCI { public void open(); public void close();}/* * 电脑运行。 */public class ReflectTest { public static void main(String[] args) throws Exception { Mainboard mb = new Mainboard(); mb.run(); //每次添加一个设备都需要修改代码传递一个新创建的对象 //mb.usePCI(new SoundCard()); //能不能不修改代码就可以完成这个动作。 //不用new来完成,而是只获取其class文件。在内部实现创建对象的动作。 File configFile = new File("pci.properties"); Properties prop = new Properties(); FileInputStream fis = new FileInputStream(configFile); prop.load(fis); for(int x=0; x<prop.size(); x++){ String pciName = prop.getProperty("pci"+(x+1)); Class clazz = Class.forName(pciName);//用Class去加载这个pci子类。 PCI p = (PCI)clazz.newInstance(); mb.usePCI(p); } fis.close(); }}pci.properties文件pci1=cn.itcast.reflect.test.SoundCardpci2=cn.itcast.reflect.test.NetCard
阅读全文
0 0
- JAVA SE学习笔记
- Java se笔记_2
- JAVA SE 笔记
- Java SE 详细笔记
- JAVA SE 学习笔记
- java se 集合 笔记
- java se 学习笔记
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- < 笔记 > Java SE
- Java SE 自学笔记1
- linux 文件操作命令
- klocwork 12.2
- log4j的配置和使用
- learn python第四章:异常处理机制和文件夹(第二节:异常处理机制)
- POJ 1721 CARDS(置换+循环节)
- < 笔记 > Java SE
- VS Code C++开发常用文件过滤设置
- Python 基础
- 回调函数的来源
- AWK快速入门
- python学习里的常见IT英语
- (二)c#整合zeroIce
- 最大栈
- 计算2的N次方