1、反射:
通过一个Class文件对象去使用该文件对象中的成员变量,构造方法,成员方法。 我们之前去使用成员的时候,先有一个java文件,然后在实例化的时候,直接new就完事了 Person p = new Person() p.eat(); 总归来说,底层还是依赖一个class文件 也就是需要先得到一个Class文件对象。 class类: 成员变量: Field 构造方法: Constructor 成员方法: Method 获取一个类对应的Class文件对象: 方式1: 通过Object类中的getClass()方法,返回此Object的运行时类。 方式2: 在不new对象的前提下,获取该类的class文件对象,使用类的静态属性class来获取。 方式3: public static Class<?> forName(String className) 返回与给定字符串名称的类或接口相关联的类对象。 -- 多数
public class Person {
//成员变量
private String name;
int age;
protected String address;
public String id;
//构造方法
Person(){}
public Person(String id){
this.id = id;
}
private Person(String name,int age){
this.name = name;
this.age = age;
}
protected Person(String name,int age,String address){
this.name = name;
this.age = age;
this.address = address;
}
//成员方法
public void fun1(){
System.out.println("这是公共的方法fun1");
}
private void fun2(String s){
System.out.println("这是私有的方法fun2"+s);
}
protected void fun3(){
System.out.println("这是被保护的方法fun3");
}
void fun4(){
System.out.println("这是默认修饰符的方法fun4");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", id='" + id + '\'' +
'}';
}
}
public class ReflexDemo {
public static void main(String[] args) {
//方式1: 通过Object类中的getClass()方法,返回此Object的运行时类
Person p = new Person();
Class<? extends Person> c1 = p.getClass();
Person p2 = new Person();
Class<? extends Person> c2 = p2.getClass();
System.out.println(c1 == c2); // true
//方式2: 在不new对象的前提下,获取该类的class文件对象,使用类的静态属性class来获取
Class<Person> c3 = Person.class;
System.out.println(c1 == c3); // true
System.out.println(c2 == c3); // true
//方式3: public static Class<?> forName(String className) 返回与给定字符串名称的类或接口相关联的类对象。
try {
Class<?> c4 = Class.forName("com.wy.day27.fanshe.Person");
System.out.println(c1 == c4); // true
System.out.println(c2 == c4); // true
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
2、通过反射获取Class文件对象中的构造方法并使用:
1、获取所有的公共构造方法: public Constructor<?>[] getConstructors() 2、获取所有的构造方法,包括私有,被保护的,默认的,公共的: public Constructor<?>[] getDeclaredConstructors() 3、获取单个公共的构造方法: public Constructor<T> getConstructor(类<?>... parameterTypes) 4、获取单个的构造方法,根据参数可以是私有,被保护的,默认的,公共的: public Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 5、通过构造方法去创建对象: public T newInstance(Object... initargs) private修饰的构造方法不能随意赋值,否则报错:IllegalAccessException 解决方法: 暴力访问 setAccessible(true) 值为true,表示反射的对象在使用的时候取消Java语言的访问检查
public class Person {
//成员变量
private String name;
int age;
protected String address;
public String id;
//构造方法
Person(){}
public Person(String id){
this.id = id;
}
private Person(String name,int age){
this.name = name;
this.age = age;
}
protected Person(String name,int age,String address){
this.name = name;
this.age = age;
this.address = address;
}
//成员方法
public void fun1(){
System.out.println("这是公共的方法fun1");
}
private void fun2(String s){
System.out.println("这是私有的方法fun2"+s);
}
protected void fun3(){
System.out.println("这是被保护的方法fun3");
}
void fun4(){
System.out.println("这是默认修饰符的方法fun4");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", id='" + id + '\'' +
'}';
}
}
public class ReflexDemo1 {
public static void main(String[] args) throws Exception {
//1、获取Class文件对象
//public static Class<?> forName(String className) 返回与给定字符串名称的类或接口相关联的类对象。
Class<?> c1 = Class.forName("com.wy.day27.fanshe.Person");
//2、获取所有的公共构造方法
//public Constructor<?>[] getConstructors()
Constructor<?>[] con1 = c1.getConstructors();
for (Constructor c : con1) {
System.out.println(c);
}
System.out.println("======================================");
//3、获取所有的构造方法,包括私有,被保护的,默认的,公共的
//public Constructor<?>[] getDeclaredConstructors()
Constructor<?>[] cons2 = c1.getDeclaredConstructors();
for (Constructor c : cons2) {
System.out.println(c);
}
System.out.println("======================================");
//4、获取单个公共的构造方法
//public Constructor<T> getConstructor(类<?>... parameterTypes)
// Constructor<?> con3 = c1.getConstructor(); //相当于获取无参构造方法,而无参构造方法是默认类型的,报错:NoSuchMethodException
// System.out.println(con3);
Constructor<?> con3 = c1.getConstructor(String.class); // 根据参数确定是public修饰的构造方法
System.out.println(con3);
System.out.println("======================================");
//5、获取单个的构造方法,根据参数可以是私有,被保护的,默认的,公共的
//public Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
Constructor<?> con4 = c1.getDeclaredConstructor(String.class, int.class); // 根据参数确定是private修饰的构造方法
System.out.println(con4);
System.out.println("======================================");
//6、通过构造方法去创建对象
//public T newInstance(Object... initargs)
Person p = (Person) con3.newInstance("1001"); // 给公共的构造方法赋值
System.out.println(p);
// Object o = con4.newInstance("你好",23); // private修饰的构造方法不能随意赋值,否则报错:IllegalAccessException
// System.out.println(o);
//暴力访问
//setAccessible(true) 值为true,表示反射的对象在使用的时候取消Java语言的访问检查
con4.setAccessible(true);
Person p1 = (Person) con4.newInstance("昭阳", 18);
System.out.println(p1);
}
}
3、通过反射获取成员变量并使用:
1、获取所有的公共成员变量: public Field[] getFields() 2、获取当前类中所有成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段: public Field[] getDeclaredFields() 3、获取单个的公共成员变量: public Field[] getField() 根据参数确定成员变量 4、将指定对象上的成员变量赋上一个新的值: void set(Object obj, Object value) 5、获取当前类中单个的成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段: public Field[] getDeclaredField() 给private修饰的成员变量赋值,需要暴力访问。 setAccessible(true) public、protected、默认的不需要。
public class Person1 {
//成员变量
private String name;
int age;
protected String address;
public String id;
//构造方法
public Person1(){} // 相较于Person ,将无参构造方法加上了public
public Person1(String id){
this.id = id;
}
private Person1(String name,int age){
this.name = name;
this.age = age;
}
protected Person1(String name,int age,String address){
this.name = name;
this.age = age;
this.address = address;
}
//成员方法
public void fun1(){
System.out.println("这是公共的方法fun1");
}
private void fun2(){
System.out.println("这是私有的方法fun2");
}
protected void fun3(){
System.out.println("这是被保护的方法fun3");
}
void fun4(){
System.out.println("这是默认修饰符的方法fun4");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", id='" + id + '\'' +
'}';
}
}
public class ReflexDemo2 {
public static void main(String[] args) throws Exception {
//1、获取字节码文件对象
Class<?> c1 = Class.forName("com.wy.day27.fanshe.Person1");
//2、获取所有的公共成员变量
//public Field[] getFields()
Field[] f = c1.getFields();
for (Field field : f) {
System.out.println(field);
}
System.out.println("==========================================");
//3、获取当前类中所有成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段
//public Field[] getDeclaredFields()
Field[] f1 = c1.getDeclaredFields();
for (Field field : f1) {
System.out.println(field);
}
System.out.println("=========================================");
//获取公共的无参构造方法
Constructor<?> con = c1.getConstructor();
//利用无参构造方法创建对象
Object o = con.newInstance();
System.out.println(o); // Person{name='null', age=0, address='null', id='null'}
//4、获取单个的公共成员变量
//public Field[] getField()
Field id = c1.getField("id"); // 根据"id"获取到id成员变量
// Field name = c1.getField("name"); // 根据"name"获取到name成员变量
// System.out.println(name); // 但是name是private修饰的,报错:NoSuchFieldException
//5、将指定对象上的成员变量赋上一个新的值
//void set(Object obj, Object value)
id.set(o, "1002"); // 将无参构造方法创建的对象上的成员变量赋上新的值
System.out.println(o); // Person{name='null', age=0, address='null', id='1002'}
System.out.println("=========================================");
//6、获取当前类中单个的成员变量,包括公共,受保护,默认和私有字段,不包括继承的字段
//public Field[] getDeclaredField()
Field name1 = c1.getDeclaredField("name"); // 根据"name"获取到name成员变量
System.out.println(name1);
//因为name是private修饰的,要想赋值,就需要暴力访问
name1.setAccessible(true);
//给成员变量赋值
name1.set(o, "昭阳");
System.out.println(o); // Person{name='昭阳', age=0, address='null', id='1002'}
System.out.println("=========================================");
//获取被protected修饰的成员变量,不需要暴力访问
Field address = c1.getDeclaredField("address");
address.set(o, "安徽合肥");
System.out.println(o); // Person{name='昭阳', age=0, address='安徽合肥', id='1002'}
System.out.println("==========================================");
//获取默认的修饰符修饰的成员变量并赋值,不需要暴力访问
Field age = c1.getDeclaredField("age");
age.set(o, 20);
System.out.println(o); // Person{name='昭阳', age=20, address='安徽合肥', id='1002'}
}
}
4、通过反射获取成员方法并使用:
1、获取本类和父类中所有的公共方法 public 方法[] getMethods() 2、获取本类的所有的方法,包括私有,不能获取父类的 public 方法[] getDeclaredMethods() 3、获取单个公共的方法并调用 public 方法 getMethod() 4、通过对象调用方法 public Object invoke(Object obj, Object... args) 第一个参数指的是调用方法的对象,第二个参数指的是实际需要传入的数据(实参) 5、获取单个的成员方法,包括公共,受保护,默认和私有字段 public 方法 getDeclaredMethod() 调用private修饰的成员方法,需要暴力访问。 setAccessible(true) public、protected、默认的不需要。
public class Person2 {
//成员变量
private String name;
int age;
protected String address;
public String id;
//构造方法
public Person2(){}
public Person2(String id){
this.id = id;
}
private Person2(String name, int age){
this.name = name;
this.age = age;
}
protected Person2(String name, int age, String address){
this.name = name;
this.age = age;
this.address = address;
}
//成员方法
public void fun1(){
System.out.println("这是公共的方法fun1");
}
private void fun2(String s){
System.out.println("这是私有的方法fun2"+s);
} // 相较于Person1 ,将private方法加上了参数String
protected void fun3(){
System.out.println("这是被保护的方法fun3");
}
void fun4(){
System.out.println("这是默认修饰符的方法fun4");
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
", id='" + id + '\'' +
'}';
}
}
public class ReflexDemo3 {
public static void main(String[] args) throws Exception {
//1、获取字节码文件对象
Class<?> c1 = Class.forName("com.wy.day27.fanshe.Person2");
//2、获取本类和父类中所有的公共方法
//public 方法[] getMethods()
Method[] methods = c1.getMethods();
for (Method m : methods) {
System.out.println(m);
}
System.out.println("=========================================");
//3、获取本类的所有的方法,包括私有,不能获取父类的
//public 方法[] getDeclaredMethods()
Method[] methods2 = c1.getDeclaredMethods();
for (Method m : methods2) {
System.out.println(m);
}
System.out.println("=========================================");
//4、获取单个公共的方法并调用
//public 方法 getMethod()
Method fun1 = c1.getMethod("fun1"); // 通过"fun1"调用了fun1()方法
// Method fun2 = c1.getMethod("fun2", String.class); // 调用fun2()方法
// System.out.println(fun2); // 但是fun2()是private修饰的,报错:NoSuchFieldException
//获取无参构造方法
Constructor<?> cons = c1.getConstructor();
Object o = cons.newInstance();
//5、通过对象调用方法
//public Object invoke(Object obj, Object... args) 第一个参数指的是调用方法的对象,第二个参数指的是实际需要传入的数据(实参)
fun1.invoke(o); // 调用了fun1()方法,输出 : 这是公共的方法fun1
System.out.println("========================================");
//6、获取单个的成员方法,包括公共,受保护,默认和私有字段
//public 方法 getDeclaredMethod()
Method fun2 = c1.getDeclaredMethod("fun2", String.class); // 调用fun2()方法
//因为fun2()是private修饰的,要想调用,就需要暴力访问
fun2.setAccessible(true); //只有私有的方法调用需要暴力访问
fun2.invoke(o,"数加科技"); // 调用了fun2()方法,输出 : 这是私有的方法fun2数加科技
System.out.println("=========================================");
//调用被protected修饰的成员方法,不需要暴力访问
Method fun3 = c1.getDeclaredMethod("fun3"); // 调用fun3()方法
fun3.invoke(o); // 这是被保护的方法fun3
System.out.println("=========================================");
//调用默认修饰的成员方法,不需要暴力访问
Method fun4 = c1.getDeclaredMethod("fun4"); // 调用fun4()方法
fun4.invoke(o); // 这是默认修饰符的方法fun4
}
}