反射机制
Posted xiaokw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了反射机制相关的知识,希望对你有一定的参考价值。
反射机制的相关类
- java.lang.reflect.*
- java.lang.Class
- 代表整个字节码,代表一个类型
- java.lang.reflect.Method
- 代表字节码中的方法字节码
- java.lang.reflect.Constructor
- 代表字节码中的构造方法字节码
- java.lang.reflect.Field
- 代表字节码中的属性字节
获取类字节码的三种方式
- 第一种:Class c = Class.forName("完整的类名带包名,如:java.lang.String");
- 第二种:Class c = 对象.getClass();
- 第三种:Class c = 任何类型.class;
package cn.xiaokw.java.reflect;
public class Demo_1 {
public static void main(String[] args) {
//第一种方式
Class c1 = null;
Class c2 = null;
Class c3 = null;
try {
c1 = Class.forName("java.lang.String");
c2 = Class.forName("java.util.Date");
c3 = Class.forName("java.lang.Integer");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//第二种方式
String str = "abc";
Class x = str.getClass();
Date date = new Date();
Class y = date.getClass();
Integer integer = 10;
Class z = integer.getClass();
System.out.println(x == c1); //true
System.out.println(y == c2); //true
System.out.println(z == c3); //true
//第三种方式
Class a = String.class;
Class b = Date.class;
Class c = int.class;
Class d = double.class;
System.out.println(a == x); //true
}
}
获取到Class,能干什么
通过Class的newInstance()方法来实例化对象。
注意;newInstance()方法内部实际上调用了无参构造方法,必须保证无参构造存在才可以
package cn.xiaokw.java.reflect;
public class Demo_2 {
public static void main(String[] args) {
try {
Class c = Class.forName("cn.xiaokw.java.reflect.User");//同样可用 Class c = User.class;
//newInstance() 这个方法是调用User这个类的无参构造方法,完成对象的创建
//重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
User user = (User) c.newInstance();
System.out.println(user.a); //abc
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
class User {
String a = "abc";
User(){
System.out.println("这里是无参构造方法");
}
}
反射机制的灵活性
package cn.xiaokw.java.reflect;
public class Demo_3 {
public static void main(String[] args) throws Exception{
FileReader reader = new FileReader("src\\cn\\xiaokw\\java\\reflect\\classinfo.properties");
//Properties是一个Map集合,key和value都是String类型
//通过使用Properties将classinfo.properties文件加载到Peroperties对象当中
Properties properties = new Properties();
//加载
properties.load(reader);
//关闭流
reader.close();
String className = properties.getProperty("className");//对应classinfo.properties文件中的key来获取value
Class c = Class.forName(className);
Object obj = c.newInstance();
System.out.println(obj); //Tue Jun 30 11:47:57 CST 2020
}
}
Class.forName()发生了什么
重点
? 如果你只是希望一个类的静态代码块执行,其他代码一律不执行
? 你可以使用:
? Class.forName("完整类名");
? 这个方法的执行会导致类加载,类加载时,静态代码块执行
package cn.xiaokw.java.reflect;
public class Demo_4 {
public static void main(String[] args) {
try {
Class.forName("cn.xiaokw.java.reflect.MyClass"); //MyClass类中的静态代码块执行了....
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class MyClass {
static {
System.out.println("MyClass类中的静态代码块执行了....");
}
}
获取文件的绝对路径
package cn.xiaokw.java.util;
/*
获取类根路径下文件的绝对路径
适用于Windows Linux
*/
public class AbsolutePath {
public static void main(String[] args) {
//采用以下的代码可以拿到一个文件的绝对路径
//从类的根路径(src)下作为起点开始
String path = Thread.currentThread().getContextClassLoader()
.getResource("cn/xiaokw/java/util/userinfo").getPath();
/*
解释:
Thread.currentThread() 当前线程对象
getContextClassLoader() 是线程对象的方法,可以获取到当前类加载器的对象。
getResource() [获取资源] 这是类加载器对象的方法,当前线程的类加载器默认从类的根路径下加载资源
*/
System.out.println(path);
///C:/Users/20131/IdeaProjects/StudyJava/out/production/StudyJava/cn/xiaokw/java/util/userinfo
}
}
以流的形式返回
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("cn/xiaokw/java/reflect/classinfo.properties");
package cn.xiaokw.java.reflect;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class Demo_5 {
public static void main(String[] args) throws IOException {
//以流的形式返回,前提是需要把文件放在src类的根目录下
InputStream is = Thread.currentThread().getContextClassLoader()
.getResourceAsStream("cn/xiaokw/java/reflect/classinfo.properties");
Properties properties = new Properties();
properties.load(is);
String className = properties.getProperty("className");
System.out.println(className);
}
}
资源绑定器
资源绑定器:只能绑定xxx.properties文件。并且这个文件必须在类src路径下。文件扩展名必须是properties
并且在写路径的时候,路径后面的扩展名不能写
package cn.xiaokw.java.reflect;
import java.util.ResourceBundle;
public class Demo_6 {
public static void main(String[] args) {
ResourceBundle bundle = ResourceBundle.getBundle("cn/xiaokw/java/reflect/classinfo");
String className = bundle.getString("className");
System.out.println(className);
}
}
获取类的父类和父接口
package cn.xiaokw.java.reflect;
public class Demo_13 {
public static void main(String[] args) throws Exception{
Class myClass = Class.forName("java.lang.String");
//获取String类的父类
Class superclass = myClass.getSuperclass();
System.out.println(superclass.getSimpleName());
//获取String类实现的所有接口
Class[] interfaces = myClass.getInterfaces();
for (Class c : interfaces){
System.out.println(c.getName());
}
}
}
属性 Field
获取Field(属性)
package cn.xiaokw.java.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Date;
public class Demo_7 {
public static void main(String[] args) throws Exception {
//获取整个类
Class c = Class.forName("cn.xiaokw.java.reflect.Student");
//获取类中的所有Field(属性)
// Field[] fields = c.getFields(); //getFields()方法只能获取public修饰的属性
Field[] fields = c.getDeclaredFields(); // 获取全部属性
//获取类的名字
// String StudentName = c.getName(); //获取的完整名字 cn.xiaokw.java.reflect.Student
String StudentName = c.getSimpleName(); //获取的简名字 Student
System.out.println(StudentName + "中有" + fields.length + "个属性");
System.out.println("-----------------------------");
for (Field f : fields) {
//获取属性的修饰符
int fModifiers = f.getModifiers();//获取对应修饰符的代号
String modifiers = Modifier.toString(fModifiers); //实现代码转修饰符字符串
System.out.print(modifiers + " ");
//获取属性的类型 如:int String double...
Class fieldType = f.getType();
// String fileTypeName = fieldType.getName(); //java.lang.String int java.util.Date...
String fileTypeName = fieldType.getSimpleName(); //获取类型简单名称
System.out.print(fileTypeName + " ");
//获取属性的名称
String fieldName = f.getName();
System.out.print(fieldName);
System.out.println();
}
}
}
class Student {
private String name;
public int age;
protected Date birthday;
String sex;
public final static double PI = 3.14159265;
}
执行结果
Student中有5个属性
---------------------------
private String name
public int age
protected Date birthday
String sex
public static final double PI
利用反射机制,反编译一个类的属性
package cn.xiaokw.java.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Date;
public class Demo_7_1 {
public static void main(String[] args) throws Exception {
StringBuilder sb = new StringBuilder();
Class person = Class.forName("cn.xiaokw.java.reflect.Person");
sb.append(Modifier.toString(person.getModifiers()) + " class " + person.getSimpleName() + "{
");
Field[] fields = person.getDeclaredFields();
for (Field field : fields) {
sb.append(" ");
sb.append(Modifier.toString(field.getModifiers())); //获取属性的修饰符
sb.append(" ");
sb.append(field.getType().getSimpleName()); //获取属性的类型
sb.append(" ");
sb.append(field.getName()); //获取属性的名字
sb.append(";
");
}
sb.append("}");
System.out.println(sb);
}
}
class Person {
private String name;
private String sex;
private int age;
private Date birthday;
}
输出结果
class Person{
private String name;
private String sex;
private int age;
private Date birthday;
}
反射机制访问对象属性,给属性赋值
package cn.xiaokw.java.reflect;
import java.lang.reflect.Field;
import java.util.Date;
public class Demo_8 {
public static void main(String[] args) throws Exception{
Class person = Class.forName("cn.xiaokw.java.reflect.Person1");
Object obj = person.newInstance();
Field field = person.getDeclaredField("name");//获取name属性 无法获取private私有属性
// field.setAccessible(true); //如果是private私有属性则加上这句“打破封装”,缺点,这样设置完后,在外部也是可以访问private的
field.set(obj , "张三"); //给obj对象中name属性赋值
System.out.println(field.get(obj)); //获取obj中name的值 输出:张三
}
}
class Person1 {
public String name;
public String sex;
public int age;
public Date birthday;
}
方法 Method
反射Method
package cn.xiaokw.java.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Demo_9 {
public static void main(String[] args) throws Exception {
Class myClass = Class.forName("cn.xiaokw.java.reflect.MyClass1");
Method[] methods = myClass.getDeclaredMethods(); //获取类的全部方法
for (Method method : methods) {
//获取方法的修饰符
int modifiers = method.getModifiers();
String s = Modifier.toString(modifiers);
System.out.print(s + " ");
//获取方法的返回类型
Class returnType = method.getReturnType();
String simpleName = returnType.getSimpleName();
System.out.print(simpleName + " ");
//获取方法名
String name = method.getName();
System.out.print(name + "(");
//获取方法的参数列表
//获取方法的参数列表类型
Class[] parameterTypes = method.getParameterTypes();
for (Class c : parameterTypes) {
System.out.print(c.getSimpleName() + " ");
}
System.out.println(")");
}
}
}
class MyClass1 {
public boolean method1(String a, int b) {
return true;
}
public void method2() {
System.out.println("method2");
}
}
反编译Method
package cn.xiaokw.java.reflect;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class Demo_9_1 {
public static void main(String[] args) throws Exception {
StringBuilder sb = new StringBuilder();
Class myClass = Class.forName("cn.xiaokw.java.reflect.MyClass1");
Method[] methods = myClass.getDeclaredMethods(); //获取类的全部方法
sb.append(Modifier.toString(myClass.getModifiers()) + " class " + myClass.getSimpleName() + "{
");
for (Method method : methods) {
sb.append(" ");
sb.append(Modifier.toString(method.getModifiers())); //获取方法修饰符
sb.append(" ");
sb.append(method.getReturnType()); //获取方法返回值类型
sb.append(" ");
sb.append(method.getName()); //获取方法名
sb.append("(");
Class<?>[] parameterTypes = method.getParameterTypes(); //获取方法参数列表类型
for (Class parameterType : parameterTypes) {
sb.append(parameterType.getSimpleName());
sb.append(",");
}
if(parameterTypes.length != 0) //判断 如果方法参数列表为空则不删除","号
sb.deleteCharAt(sb.length() - 1);
sb.append("){}
");
}
sb.append("}");
System.out.println(sb);
}
}
反射机制调用方法
package cn.xiaokw.java.reflect;
import java.lang.reflect.Method;
public class Demo_10 {
public static void main(String[] args) throws Exception {
Class myClass = Class.forName("cn.xiaokw.java.reflect.MyClass1");
//获取Method
Method method = myClass.getMethod("method1", String.class, int.class);//使用形参区分重载的方法
Object obj = myClass.newInstance();
/*
调用方法的四要素:
对象是 obj
参数是 "abc" 10
方法是 method
返回值是 abc
*/
Object abc = method.invoke(obj, "abc", 10); //使用obj对象调用MyClass1类中的method1方法
System.out.println(abc); //true
}
}
构造方法 Constructor
反编译Constructor
package cn.xiaokw.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Demo_11 {
public static void main(String[] args) throws Exception{
Class myClass = Class.forName("cn.xiaokw.java.reflect.Person2");
Constructor[] constructor = myClass.getConstructors();
StringBuilder sb = new StringBuilder();
sb.append(Modifier.toString(myClass.getModifiers())+" class " +myClass.getSimpleName() + " {
");
for (Constructor con :constructor){
sb.append(" ");
sb.append(Modifier.toString(con.getModifiers())); //获取构造方法的修饰符
sb.append(" ");
sb.append(myClass.getSimpleName()); //构造方法名就是类名
sb.append("(");
Class[] parameterTypes = con.getParameterTypes(); //获取构造方法的参数
for (Class c :parameterTypes){
sb.append(c.getSimpleName());
sb.append(",");
}
if (parameterTypes.length >0)
sb.deleteCharAt(sb.length() -1);
sb.append("){}
");
}
sb.append("}");
System.out.println(sb);
}
}
class Person2 {
private String no;
private String name;
private int age;
public Person2() {
}
public Person2(String no) {
this.no = no;
}
public Person2(String no, String name) {
this.no = no;
this.name = name;
}
public Person2(String no, String name, int age) {
this.no = no;
this.name = name;
this.age = age;
}
}
输出结果
class Person2 {
public Person2(String,String,int){}
public Person2(String,String){}
public Person2(String){}
public Person2(){}
}
反射机制调用构造方法
package cn.xiaokw.java.reflect;
import java.lang.reflect.Constructor;
public class Demo_12 {
public static void main(String[] args) throws Exception {
Class teacher = Class.forName("cn.xiaokw.java.reflect.Teacher");
//调用无参构造方法一:
Object obj = teacher.newInstance();
System.out.println(obj); //Teacher{name=‘null‘, id=‘null‘, sex=‘null‘}
//调用无参构造方法二:
Constructor c = teacher.getDeclaredConstructor();
Object o = c.newInstance();
System.out.println(o); //Teacher{name=‘null‘, id=‘null‘, sex=‘null‘}
//调用有参构造方法
//使用形参区分构造方法
Constructor c1 = teacher.getDeclaredConstructor(String.class, String.class);
Object zhangsan = c1.newInstance("张三", "100001");
System.out.println(zhangsan); //Teacher{name=‘张三‘, id=‘100001‘, sex=‘null‘}
Constructor c2 = teacher.getDeclaredConstructor(String.class, String.class, String.class);
Object lishi = c2.newInstance("李四", "100002", "男");
System.out.println(lishi); //Teacher{name=‘李四‘, id=‘100002‘, sex=‘男‘}
}
}
class Teacher {
String name;
String id;
String sex;
public Teacher() {
}
public Teacher(String name, String id) {
this.name = name;
this.id = id;
}
public Teacher(String name, String id, String sex) {
this.name = name;
this.id = id;
this.sex = sex;
}
@Override
public String toString() {
return "Teacher{" +
"name=‘" + name + ‘‘‘ +
", id=‘" + id + ‘‘‘ +
", sex=‘" + sex + ‘‘‘ +
‘}‘;
}
}
以上是关于反射机制的主要内容,如果未能解决你的问题,请参考以下文章