JavaSE 反射
反射
框架设计的灵魂: 反射。
<链接:https://pan.baidu.com/s/1BTbpEghJ1XT53duNvkmiQg
提取码:1234
复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V3的分享>
框架: 半成品软件。可以在框架的基础进行软件开发,简化编码。
概念: 将类的各个组成部分封装为其他对象,这就是反射机制。

好处: 1. 可以在程序运行过程中,操作这些对象。 获取、操作
2.可以解耦,提高程序的可扩展性。
获取class 对象的方式:
1.Class.forName("全类名") ,将字节码文件加入到内存
多用于配置文件,将类名定义在配置文件中,读取文件,加载类
2.类名.class : 通过类名的属性class 获取
多用于参数的传递
3.对象.getClass() :getClass 方法在object 类中定义的。
多用于对象的获取字节码的方式
结论:
同一个字节码文件(*.class) 在一次程序运行过程中,只会被加载一次,相对应的对象也会只会创建一个,不论通过哪一种方式
反射:就是通过class文件对象,去使用该文件中的成员变量、构造方法和成员方法。
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
想要解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
Class类:
成员变量 Field
构造方法 Constructor
成员方法 Method
得到这个类的对象,通过这个类的对象去调用方法,使用该方法
获取class文件对象的三种方式
-
Object类的getClass()方法

-
数据类型的静态属性class

-
Class中的静态方法
API格式:
public static Class forName(String className)
一般使用过程中选择:
自己使用时,可以任意选择,推荐第二种更方便。
做开发工作时,通常选择使用第三种。
通过反射获取构造方法并使用
Person类:
package com.demo06;
public class Person {
private String name;
int age;
public String hobby;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person(String name, int age, String hobby) {
this.name = name;
this.age = age;
this.hobby = hobby;
}
public void show(){
System.out.println("show");
}
public Person(){}
public void Person(int age, String hobby) {
this.age = age;
this.hobby = hobby;
}
private Person(String name,String hobby){
this.name = name;
this.hobby = hobby;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", hobby='" + hobby + '\'' +
'}';
}
}
通过反射获取构造方法并使用
package com.demo06;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class Test01 {
////////通过反射获取构造方法并使用
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取字节码文件对象
Class c = Class.forName("com.demo06.Person");
//获取构造方法
// public Constructor[] getConstructors(); //获取所有的公共(public)构造方法
//public Constructor[] getDeclaredConstructors(); 获取所有的构造方法
// Constructor[] cons = c.getDeclaredConstructors();
// Constructor[] cons2 = c.getConstructors();
// for (Constructor con : cons2) {
// System.out.println(con);
// }
//获取单个构造方法
//public Constructor<T> getConstructor(Class<?>...parameterTypes)
//这里参数所表示的是: 想要获取的构造方法的构造参数个数以及数据类型的class字节码文件对象
Constructor con = c. getConstructor(); // 返回的是构造方法对象
// System.out.println(con);
// Person p = new Person;
// System.out.println(p);
// public T newInstance(Object...initargs)
// 使用此Constructor 对象表示的方法来创建该构造方法的声明类的辛实例,并用指定的初始化参数初始化该实例。
Object o = con.newInstance();
System.out.println(o);
//////
// Person p = (Person)o;
// System.out.println(p);
// p.show();
}
}
示例1:
package com.demo06;
import java.lang.reflect.Constructor;
public class Test02 {
public static void main(String[] args) throws Exception{
// 需求: 通过反射去获取该构造方法并使用
// public Person(String name, int age, String hobby)
// Person p = new Person("22",22,"22");
// System.out.println(p);
// 获取字节码文件对象
Class c = Class.forName("com.demo06.Person");
// 获取带参构造方法对象
// public Constructor<T> getConstructor(Class<?>...parameterTypes)
Constructor con = c.getConstructor(String.class,int.class,String.class);
// 通过带参构造方法创建对象
// public T newInstance(Object...initargs)
Object o = con.newInstance("22",22,"22");
System.out.println(o);
}
}
示例2:
package com.demo06;
import java.lang.reflect.Constructor;
public class Test03 {
// 需求: 通过反射获取私有构造方法并使用
//private Person(String name,String hobby)
// Person p = new Person("小明","运动");
// System.out.println(p)
public static void main(String[] args) throws Exception{
//获取字节码对象
Class c = Class.forName("com.demo06.Person");
//获取私有构造方法对象
// NoSuchMethodException 找不到这个对应的方法异常
// 原因是使用的方法只能获取公共方法 Constructor con = c.getConstructor(String.class,String.class);
// 使用下面这种方法即可
Constructor con = c.getDeclaredConstructor(String.class,String.class);
//用该私有构造方法创建对象
// IllegalAccessException 非法的访问异常 没有访问pravate的权限
// 暴力访问即可
con.setAccessible(true); // 使用boolean值
Object o = con.newInstance("小明", "运动");
System.out.println(o);
}
}
示例3:
package com.demo06;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Test04 {
// 需求 : 通过反射获取成员变量并使用
// public Person(String name, int age, String hobby)
public static void main(String[] args) throws Exception{
// 获取字节码文件对象
Class c = Class.forName("com.demo06.Person");
//获取所有的成员变量
//Field[] fields = c.getFields();
// Field[] fields = c.getDeclaredFields();
// for (Field field:fields){
// System.out.println(field);
// }
//通过无参构造物方法创建对象
Constructor con = c.getConstructor();
Object o = con.newInstance();
System.out.println(o);
//获取单个成员变量
//获取name并对其赋值
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
//public void set(Object obj,Object value)
//将指定对象变量上此Field对象表示的字段设置为指定的新值
nameField.set(o,"小明");
System.out.println(o);
//获取age并对其赋值
Field ageField = c.getDeclaredField("age");
ageField.set(o,12);
System.out.println(o);
//获取hobby并对其赋值
Field hobbyField = c.getDeclaredField("hobby");
hobbyField.set(o,"运动"); ///表达的意义为,调用set给o的Field字段赋值“运动”
System.out.println(o);
}
}
通过反射获取成员方法并使用
示例1:
package com.demo06;
////无参返回
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Test05 {
public static void main(String[] args) throws Exception{
//获取字节码文件对象
Class c = Class.forName("com.demo06.Person");
//获取所有的方法
// Method[] methods = c.getMethods(); // 获取本类以及父类的public方法
// Method[] me = c.getDeclaredMethods(); //获取自己的所有方法
// for (Method method: me){
// System.out.println(method);
// }
Constructor con = c.getConstructor();
Object o = con.newInstance();
//获取单个方法并使用
//public void show()
//public Method getMethod(String name,Class<?>...parameterTypes)
//第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
Method m1 = c.getMethod("show");
//o.mi(); //错误
//public Object invoke(Object obj,Object...args)
//返回值是Object接收,第一个参数表示对象是谁,第二个参数表示调用该方法的实际参数
m1.invoke(o);
}
}
示例2:
//带参返回 接在示例1后
// private Person(String name,String hobby)
Method person = c.getMethod("Person", int.class, String.class);
person.setAccessible(true);
person.invoke(o,12,"运动");

浙公网安备 33010602011771号