大数据预科21(补充之反射)
来源:互联网 发布:淘宝卖蜂蜜要什么条件 编辑:程序博客网 时间:2024/04/29 12:39
反射
类的加载
- 使用类时,类未被加载到内存中--加载,连接,初始化
- 加载:将class文件读入内存,并为之创建一个class对象,任何类被使用时系统都会建立一个class对象
- 连接
- 验证 是否有正确的内部结构,并和其他类协调一致
- 准备 负责为类的静态成员分配内存,并设置默认初始化值
- 解析 将类的二进制数据中的符号引用替换为直接引用
- 初始化
- 调用构造函数进行初始化
- 类初始化时机创建某个类
1. 创建类的实例2. 类的静态变量,或者为静态变量赋值3. 类的静态方法4. 使用类的反射机制强制创建某个类或接口对应的java.lang.Class对象5. 初始化某个类的子类6. 直接使用java.exe来运行某个主类
- 类加载器
- 负责将.class文件加载到内存中,并为之生成class对象
- 类加载器的组成加载器
- Bootstrap ClassLoader根类加载器
- 引导类加载器,负责java核心类的加载
- System,String等,在jdk的lib目录下的rt.jar文件中
- Extension ClassLoader扩展类加载器
- JRE扩展目录中的jar目录
- jdk 下的jre下的lib下的ext目录
- System ClassLoader系统加载器
- jvm启动时加载java命令的class文件。以及classpath环境变量所指定的jar
- Bootstrap ClassLoader根类加载器
反射
- 定义
java反射机制是在运行状态,对应任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
- Class类
- Class没有公共构造方法。
- Class对象是在加载类时由java虚拟机以及通过调用类加载器中的defineClass方法自动构造的
- 获取Class对象的三种方式(获取字节码对象--Class对象为 包名.类名)
- 通过Object对象的getClass()方法
- 通过类名.class直接获取
- 通过Class的方法forName(“类名”)
- 通过反射获取
- 通过反射获取构造方法并使用
- 返回单个
- public的:getConstructor(Class<?>...parameterTypes)
- 包含private的:getDeclaredConstructor(Class<?>...parameterTypes)
- 返回多个
- public的:getConstructors()
- 包含private的:getDeclaredConstructors()
- 返回单个
- 通过反射方式,获取构造方法,创建对象
- 获取到Class对象
- 获取指定的构造方法
- 通过构造Constructor中的方法,创建对象
Class c=Class.forName("com.peng.Person"):Constructor con=c.getConstructor(String.class,int.class);Object obj=con.newInstance("张三",12);
- 通过反射方式,获取私有构造方法,创建对象
- AccessibleObject类是Filed,Method和Constructor的父类
- 它提供了将反射的对象标记在使用时取消默认java访问控制检查的能力
- setAccessible(true/false)true为取消权限,false不取消权限检查
- 步骤
1. 获取Class2. 获取指定的构造方法3. 暴力访问,通过setAccessible(true)方法4. 通过构造方法类Constructor来创建对象
Class c=Class.forName("com.peng.Person");Constructor con=c.getDeclaredConstructor(String.class,int.class);con.setAccessible(true);Object obj=con.newInstance("小明",12);
- AccessibleObject类是Filed,Method和Constructor的父类
通过反射获取成员变量并使用
- 成员变量使用Filed表示
- 方法
- getFiled(String name)--public修饰的变量
- getDeclaredFiled(String name)--任意权限
- getFileds()--获取所有public的变量
- getDeclaredFileds()--获取所有变量
实例
Class c=Class.forName("com.peng.Person");Fileds[] fileds=c.getDeclaredFileds();for(Filed filed:fileds){ System.out.println(filed);}
Filed temp=Class.forName("com.peng.Person").getFiled("age");
- Filed方法
- set(obj,值)
- get(obj)
Class c=Class.forName("com.peng.Person");Constructor con=c.getConstructor(String.class);Object obj=con.newInstance("李四");Filed filed_name=c.getFiled("name");filed_name.set(obj,"王五");filed_name.get(obj);
- 通过反射获取成员方法并使用
- Method类
- 方法(Class类方法)
- getMethod(String name,Class<?>... paraterTypes)--public的有参数的方法
- getDeclaredMethod(String name,Class<?>... paraterTypes)--任意的的代参数的方法
- getMethods()--获取全部publi的方法
- getDeclaredMethods()--获取所有方法
- 方法(Class类方法)
- 使用
Class c=Class.forName("com.peng.Person"); Constructor con=c.getDeclaredConstructor(String.class); Object obj=con.newInstance("赵六"); Method method1 = c.getDeclaredMethod("addPerson",int.class); method1.setAccessible(true);//暴力访问--private Object reslute=cmethod1.invoke(obj,12);1. 获取Class对象2. 获取构造方法3. 通过构造方法,创建对象4. 获取指定的方法5. 执行找到的方法
- Method类
练习
将已存在的ArrayList中添加String数据(泛型的擦除)
1. 创建ArrayList<Integer>对象 list2. 往list对象中添加Integer对象3. 获取ArrayList的Class4. 获取add方法5. 添加String数据
ArrayList<Integer> list = new ArrayList<Integer>();list.add(1);Class c=Class.forName("java.util.ArrayList");//这里的Object.class保证可以添加任何对象Method addMethod=c.getMthod("add",Object.class);addMethod.invoke(list,"哈哈");
package com.peng.test;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.Scanner;/** * @author kungfu~peng * @data 2017年10月9日 * @description */public class Demo1 { public static void main(String[] args) throws Exception { ArrayList<Integer> list=new ArrayList<Integer>(); list.add(1); Class c=Class.forName("java.util.ArrayList"); Method me=c.getMethod("add", Object.class); me.invoke(list, "hehge"); System.out.println(list); }}
- 反射配置文件创建对象
- 读取配置文件的过程
1. Properties prop=new Properties();2. prop.load(new FileInputStream("person.properties"));3. String name=prop.getProperty("name");
- 创建对象
1. Class对象2. 构造函数创建对象
- 读取配置文件的过程
总结
- 如何获取Class对象
- 通过Object的getClass()方法
- 类名.class
- 反射Class.forName(String className)
- 通过反射,获取类中的构造函数
- Class的对象.getConstructor(参数)
- 通过反射,new对象
- 构造对象.newInstance(实参);
- 通过反射,找到方法并执行
- Class对象.getMethod(方法名,方法参数);
- Method对象.invoke(obj,方法实参);
- 通过反射,获取成员变量
- Class对象.Filed(变量名称);
- Filed对象的方法
- set(obj,实参)
- get(obj)
练习
package testt;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;/** * @author kungfu~peng * @data 2017年10月10日 * @description */public class Person { private int age; protected String name; String sex; public int id; public Person() { super(); // TODO Auto-generated constructor stub } public Person(int age, String name, String sex, int id) { super(); this.age = age; this.name = name; this.sex = sex; this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getId() { return id; } public void setId(int id) { this.id = id; } // 方法 /** * 功能: 返回值类型: 参数列表: */ private void add() { System.out.println("add"); } /** * 功能: 返回值类型: 参数列表: */ protected void delete() { System.out.println("delete"); } /** * 功能: 返回值类型: 参数列表: */ void update() { System.out.println("update"); } /** * 功能: 返回值类型: 参数列表: */ public void query(int id) { System.out.println("query"); } // 测试 public static void main(String[] args) throws Exception { // 获取Class对象 Class c = Class.forName("testt.Person"); // 获取构造方法 Constructor con = c.getConstructor(int.class, String.class, String.class, int.class); // 通过构造方法来创建对象 Object obj = con.newInstance(12, "aa", "bb", 23); // 获取属性 Field id_Filed = c.getDeclaredField("id"); Field name_Filed = c.getDeclaredField("name"); Field sex_Filed = c.getDeclaredField("sex"); Field age_Filed = c.getDeclaredField("age"); name_Filed.setAccessible(true); id_Filed.setAccessible(true); sex_Filed.setAccessible(true); age_Filed.setAccessible(true); // 设置属性 id_Filed.set(obj, 100); name_Filed.set(obj, "100"); sex_Filed.set(obj, "100"); age_Filed.set(obj, 100); // 获取属性值 System.out.println(id_Filed.get(obj)); // 获取方法 Method me = c.getDeclaredMethod("add", null); me.setAccessible(true); me.invoke(obj, null); }}
补充
- 高内聚,低耦合--提高模块内的利用率;降低模块间的依赖。
- 反射最大作用:解耦
- 一个类的内容
1. Class--代表字节码的类--代表类的类2. Package--代表包的类3. Field--代表方法的类4. Method--代表方法的类5. Constructor--代表构造方法的类6. Annotation--代表注解的类
- 反射:剖析类,分析类的字节码,产生对应的字节码对象以及实例对象
例:模拟运行时修改配置文件不影响程序运行
- 目录结构
- src
- com.pemg.classdemo2
- Doctor.java
- Person.java
- Teacher.java
- Test.java
- com.pemg.classdemo2
- config.properties
- src
源代码
Doctor.java
package com.peng.classdemo2;import java.util.Date;/** * @author kungfu~peng * @data 2017年11月13日 * @description */public class Doctor implements Person { private String name; private int age; private char gender; private Date date; private double salary; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } @Override public void eat() { System.out.println(name + "在手术室吃饭!"); } @Override public void work() { System.out.println(name + "医生:" + date.getYear() + "年," + date.getMonth() + "月," + date.getDay() + "日" + " 在工作"); } @Override public void tax() { System.out.println(name + "交税" + salary * 0.4 + "元"); }}
Person.java
package com.peng.classdemo2;/** * @author kungfu~peng * @data 2017年11月13日 * @description */public interface Person { public void eat(); public void work(); public void tax();}
Teacher.java
package com.peng.classdemo2;import java.util.Date;/** * @author kungfu~peng * @data 2017年11月13日 * @description */public class Teacher implements Person { private String name; private int age; private char gender; private Date date; private double salary; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } @Override public void eat() { System.out.println(name + "在教室吃饭!"); } @Override public void work() { System.out.println(name + "老师:" + date.getYear() + "年," + date.getMonth() + "月," + date.getDay() + "日" + " 在工作"); } @Override public void tax() { System.out.println(name + "交税" + salary * 0.02 + "元"); }}
Test.java
package com.peng.classdemo2;import java.io.File;import java.io.FileInputStream;import java.lang.reflect.Method;import java.sql.Date;import java.text.SimpleDateFormat;import java.util.Properties;/** * @author kungfu~peng * @data 2017年11月13日 * @description 反射机制实现对类的不修改调用操作 */public class Test { @SuppressWarnings("unchecked") public static void main(String[] args) throws Exception { // 模拟运行 while (true) { Thread.sleep(10000);// 休眠期间修改config.properties的数据试试看 // 加载配置文件 Properties prop = new Properties(); prop.load(new FileInputStream(new File("src/config.properties"))); // 获取类名 String className = prop.getProperty("classname"); // 获取属性字符串 String attrName = prop.getProperty("attrname"); // 获取属性值字符串 String attrValue = prop.getProperty("attrvalue"); // 获取方法字符串 String method = prop.getProperty("methodname"); // 获取字节码对象 Class c = Class.forName(className); // 创建实例 Person p = (Person) c.newInstance(); // 获取属性名数组 String[] attrNames = attrName.split("/"); // 获取属性值数组 String[] attrValues = attrValue.split("/"); // 用setter来将属性值赋值给相应的属性--注意1setter方法名的拼接;注意2属性格式的转化 for (int i = 0; i < attrNames.length; i++) { // 获取类型 Class temp = c.getDeclaredField(attrNames[i]).getType(); // 获取setter方法 Method m = c.getMethod( "set" + Character.toString(attrNames[i].charAt(0)) .toUpperCase() + attrNames[i].substring(1), temp); // 判断类型,转换类型 if (temp.equals(String.class)) { m.invoke(p, attrValues[i]); } else if (temp == int.class || temp.equals(Integer.class)) { m.invoke(p, Integer.parseInt(attrValues[i])); } else if (temp == char.class || temp.equals(Character.class)) { m.invoke(p, attrValues[i].toCharArray()[0]); } else if (temp == Date.class) { m.invoke(p, new SimpleDateFormat().parse(attrValues[i])); } else if (double.class == temp || temp.equals(Double.class)) { m.invoke(p, Double.parseDouble(attrValues[i])); } } // 执行指定的方法 Method m = c.getMethod(method, null); m.invoke(p, null); } }}
config.properties文件
classname=com.peng.classdemo2.Doctorattrname=name/age/gender/date/salaryattrvalue=p/23/\u7537/2017-11-13/65535methodname=eat
阅读全文
0 0
- 大数据预科21(补充之反射)
- 大数据预科19(补充之线程)
- 大数据预科20(补充之网络编程)
- 大数据预科班3
- 大数据预科班4
- 大数据预科班5
- 大数据预科班6
- 大数据预科班7
- 大数据预科班8
- 大数据预科班9
- 大数据预科班串讲
- 大数据预科班10
- 大数据预科班11
- 大数据预科班12
- 大数据预科班13
- 大数据预科班14
- 大数据预科班15
- 大数据预科班16
- HDU 1013 Digital Roots
- Linux学习之C语言基础
- IntelliJ IDEA 导入简单java项目
- Hibernate框架简介(个人总结及理解)
- 01.奇特的一生——柳比歇夫一生的秘密
- 大数据预科21(补充之反射)
- cron表达式详解
- vueJs(2.x)+router+vuex简易博客系统<二>
- threeSum
- libvirt q35 报错
- ORACLE 日期加减操作
- Unreal Editor中调用exe
- 多线程爬虫案例(浅)一
- WEB API接口