您的位置:首页 > 大数据

大数据预科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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: