大数据预科21(补充之反射)
2017-11-13 18:22
267 查看
反射
类的加载
使用类时,类未被加载到内存中--加载,连接,初始化加载:将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
反射
定义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. 获取Class 2. 获取指定的构造方法 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);
通过反射获取成员变量并使用
成员变量使用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()--获取所有方法
使用
1. 获取Class对象 2. 获取构造方法 3. 通过构造方法,创建对象 4. 获取指定的方法 5. 执行找到的方法
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);
练习
将已存在的ArrayList中添加String数据(泛型的擦除)1. 创建ArrayList<Integer>对象 list 2. 往list对象中添加Integer对象 3. 获取ArrayList的Class 4. 获取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
config.properties
源代码
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.Doctor attrname=name/age/gender/date/salary attrvalue=p/23/\u7537/2017-11-13/65535 methodname=eat
相关文章推荐
- 大数据预科19(补充之线程)
- Android开发——补充SharedPreferences存储(跨Activity存取数据)
- 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二九║ Nuxt实战:异步实现数据双端渲染
- 对数据库增加数据(21)
- JDBC_利用反射及JDBC元数据编写通用的查询方法
- 怎么编程你输进去一个数据 然后输出的会是一组数列 其中前两个数字之和等于第三个数字。例如你输入7, 输出会显示1,2,3,5,8,13,21(每行显示一个数)
- 看数据结构写代码(21) 稀疏矩阵(十字链表方式)
- 大数据学习笔记-------------------(21)
- GIS 数据下载一些 ,不齐全,望能补充
- 2.2 关于Python3 数据类型的补充学习
- python-21-如何读写json数据?如何解析简单的xml文档?
- 不使用反射,“一行代码”实现Web、WinForm窗体表单数据的填充、收集、清除,和到数据库的CRUD
- JDBC:利用反射及JDBC元数据编写通用的查询方法
- List中添加多种数据类型 反射
- 利用反射实现 MVC中的 数据插入
- 通过反射转换java数据类型
- 21.2 windows_21_Library_Class_DLL_USE 动态库补充2
- java基础补充-反射
- UNP Chapter 21 - 带外数据
- 数据解析11-21