反射概述
在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性; 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。本质就是 操作字节码文件。
反射相关的类(简述)
java.lang.Class 整个类的字节码,代表整个类【一个类型】 java.lang.reflect.Method 字节码中的方法字节码,代表类中的方法 java.long.reflect.Constructor 字节码中的构造方法字节码,代表类中的构造方法 java.long.reflect.Field 字节码中的属性字节码,代表类中的成员变量和实例变量
获取字节码文件(★★★★★)
第一种:Class clazz = Class.forName(“带包名的完整类名”);
clazz_1
= Class
.forName("java.lang.String");
第二种:Class clazz = 对象.getClass();
Date date
= new Date();
Class
clazz_5 = date
.getClass();
第三种:Class clazz = 任何类型.class;
Class
clazz_7 = Integer
.class;
反射机制创建对象
获取字节码文件通过Class对象调用newInstance()完成对象的创建
调用newInstance()方法必须保证 类有无参构造方法
Class
<?> classTeacher
= Class
.forName("reflectdemo_02.Teacher");
Object o
= classTeacher
.newInstance();
System
.out
.println(o
);
反射相关的类(详解)
(1)java.lang.Class 类 (★★★★★)
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 枚举是一种类,注释是一种接口。Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造。
常用方法
(2)java.long.reflect.Field 类 (★★★)
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。 反射的字段可能是一个类(静态)字段或实例字段。
常用方法
Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。int getInt(Object obj) 获取 int 类型或另一个通过扩展转换可以转换为 int 类型的基本类型的静态或实例字段的值。int getModifiers() 以整数形式返回由此 Field 对象表示的字段的 Java 语言修饰符。String getName() 返回此 Field 对象表示的字段的名称。Class<?> getType() 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。int hashCode() 返回该 Field 的哈希码。void set(Object obj, Object value) 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。void setInt(Object obj, int i) 将字段的值设置为指定对象上的一个 int 值。String toString() 返回一个描述此 Field 的字符串。
(3)java.long.reflect.Method 类 (★★★)
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
常用方法
int getModifiers() 以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。String getName() 以 String 形式返回此 Method 对象表示的方法名称。Class<?>[] getParameterTypes() 按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。Class<?> getReturnType() 返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。int hashCode() 返回此 Method 的哈希码。Object invoke(Object obj, Object... args) 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。(★★★)String toString() 返回描述此 Method 的字符串。
(4)java.long.reflect.Constructor 类 (★★)
Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
常用方法
int getModifiers() 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符。String getName() 以字符串形式返回此构造方法的名称。Class<?>[] getParameterTypes() 按照声明顺序返回一组 Class 对象,这些对象表示此 Constructor 对象所表示构造方法的形参类型。TypeVariable<Constructor<T>>[] getTypeParameters() 按照声明顺序返回一组 TypeVariable 对象,这些对象表示通过此 GenericDeclaration 对象所表示的一般声明来声明的类型变量。int hashCode() 返回此 Constructor 的哈希码。T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。(★★★)String toString() 返回描述此 Constructor 的字符串。
通过反射机制反编译
package reflectdemo_06
;
import java
.lang
.reflect
.Constructor
;
import java
.lang
.reflect
.Field
;
import java
.lang
.reflect
.Method
;
import java
.lang
.reflect
.Modifier
;
import java
.util
.ResourceBundle
;
public class DecompilationAllReflectTest {
public static void main(String
[] args
) throws Exception
{
ResourceBundle resource
= ResourceBundle
.getBundle("classinfo");
String userClass
= resource
.getString("userClass");
Class
<?> aClass
= Class
.forName(userClass
);
StringBuilder builder
= new StringBuilder();
builder
.append(Modifier
.toString(aClass
.getModifiers()));
builder
.append(" class ");
builder
.append(aClass
.getSimpleName());
builder
.append(" {\n");
Field
[] fields
= aClass
.getDeclaredFields();
for (Field field
: fields
) {
builder
.append("\t");
builder
.append(Modifier
.toString(field
.getModifiers()));
builder
.append(" ");
builder
.append(field
.getType().getSimpleName());
builder
.append(" ");
builder
.append(field
.getName());
builder
.append(";\n");
}
builder
.append("\n");
Constructor
<?>[] declaredConstructors
= aClass
.getDeclaredConstructors();
for (Constructor
<?> constructor
: declaredConstructors
) {
builder
.append("\t");
builder
.append(Modifier
.toString(constructor
.getModifiers()));
builder
.append(" ");
builder
.append(aClass
.getSimpleName());
builder
.append("(");
Class
<?>[] parameterTypes
= constructor
.getParameterTypes();
for (Class
<?> parameterType
: parameterTypes
) {
builder
.append(parameterType
.getSimpleName());
builder
.append(",");
}
if (parameterTypes
.length
> 0) {
builder
.deleteCharAt(builder
.length() - 1);
}
builder
.append(") {...}\n");
}
builder
.append("\n");
Method
[] declaredMethods
= aClass
.getDeclaredMethods();
for (Method method
: declaredMethods
) {
builder
.append("\t");
builder
.append(Modifier
.toString(method
.getModifiers()));
builder
.append(" ");
builder
.append(method
.getReturnType().getSimpleName());
builder
.append(" ");
builder
.append(method
.getName());
builder
.append("(");
Class
<?>[] parameterTypes
= method
.getParameterTypes();
for (Class
<?> type
: parameterTypes
) {
builder
.append(type
.getSimpleName());
builder
.append(",");
}
if (parameterTypes
.length
> 0) {
builder
.deleteCharAt(builder
.length() - 1);
}
builder
.append(") {...}\n");
}
builder
.append("}");
System
.out
.println(builder
);
}
}
输出结果
public class UserService {
private String userName
;
private String passWord
;
protected String userNo
;
public UserService(String
,String
,String
) {...}
public UserService(String
,String
) {...}
public UserService(String
) {...}
public UserService() {...}
public String
toString() {...}
public void logout() {...}
public boolean login(String
,String
) {...}
}
通过反射机制创建对象(★★★★★)
1. 获取类的字节码 2. 通过字节码获取有/无参构造方法 3. 调用newInstance()方法创建对象
Class
<?> aClass
= Class
.forName("reflectdemo_07.User");
Object o
= aClass
.newInstance();
System
.out
.println(o
);
Constructor
<?> newObj
= aClass
.getDeclaredConstructor(int.class,String
.class);
Object obj
= newObj
.newInstance(1015, "小王");
System
.out
.println(obj
);
反射机制设置/获取字段值(★★★★★)
1. 获取类的字节码 2. 创建对象 3. 获得指定的字段名 4. 使用字段对象.set(Object obj,Object value)方法设置值 5. 使用字段对象.get(Object obj)方法获取值
package reflectdemo_04
;
import java
.lang
.reflect
.Field
;
public class ReflectGetValueTest {
public static void main(String
[] args
) throws Exception
{
Class
<?> aClass
= Class
.forName("reflectdemo_04.Student");
Object student
= aClass
.newInstance();
Field teacherName
= aClass
.getDeclaredField("teacherName");
teacherName
.set(student
,"王老师");
System
.out
.println("teacherName:" + teacherName
.get(student
));
Field studentNo
= aClass
.getDeclaredField("studentNo");
studentNo
.setAccessible(true);
studentNo
.set(student
,10051);
System
.out
.println("studentNo:" + studentNo
.get(student
));
}
}
反射机制调用方法(★★★★★)
1. 获取类的字节码 2. 获得指定方法 【方法名,参数类型】 3. 使用invoke(Object obj, Object... args)调用方法
调用方法四要素:
方法名对象实参 返回值
Class
<?> aClass
= Class
.forName("reflectdemo_07.User");
Object obj
= aClass
.newInstance();
Method show
= aClass
.getDeclaredMethod("show", int.class);
Object retValue
= show
.invoke(obj
,12112);
System
.out
.println(retValue
);
反射机制获取超类
package reflectdemo_07
;
public class SetGetTest {
public static void main(String
[] args
) throws Exception
{
Class
<?> aClass
= Class
.forName("java.lang.String");
Class
<?> superclass
= aClass
.getSuperclass();
System
.out
.println(superclass
);
Class
<?>[] interfaces
= aClass
.getInterfaces();
for (Class
<?> anInterface
: interfaces
) {
System
.out
.println(anInterface
.getName());
}
}
}