提示:本帖子直接上代码
文章目录
前言
首先,我们建立一个 Person 类,以下的操作需要用到。Person 类中包含了两个私有的属性和两个公有的属性,以及一个私有的有参构造方法。
class Person{
private String name;
private Integer age;
public String address;
public String id;
public Person(){
System.out.println("空参构造方法");
}
public Person(String name){
this.name = name;
}
private Person(String name,Integer age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
“csdn.ReflectionAnnotation.Reflection” 是我创建的包的名字。结构如下:
一、字节码文件对象的创建
三种字节码的文件创建形式
public static void main(String[] args) throws ClassNotFoundException {
Person p = new Person();
//1、Object类的getClass()方法
Class c = p.getClass();//获取到Person对应的Class类的对象
System.out.println(c);
//2、通过 类名.class 获取到字节码文件对象
Class c1 = Person.class;
System.out.println(c1);
//3、通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName即可)
Class c2 = Class.forName("csdn.ReflectionAnnotation.Reflection.Person");
System.out.println(c2);
}
运行结果如下所示,三种形式都可以。
二、获取构造方法
获取 Person 的构造方法
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//1、获取Person的字节码文件对象
Class c = Class.forName("csdn.ReflectionAnnotation.Reflection.Person");
Constructor[] con = c.getConstructors();//获取到Person类所有的public构造方法
for(Constructor constructor : con){
System.out.println(constructor);
}
System.out.println("-------------------------------------");
Constructor[] con1 = c.getDeclaredConstructors();//获取到Person类所有的构造方法(包括私有的)
for(Constructor constructor : con1){
System.out.println(constructor);
}
System.out.println("-------------------------------------");
Constructor con2 = c.getConstructor(String.class); //获取某一个public构造方法
System.out.println(con2);
}
运行结果:
注意第三种,获取特定的构造方法需要传入参数。
三、通过构造方法创建对象
public static void main(String[] args) throws Exception{
//获取到Person的字节码文件对象
Class c = Class.forName("csdn.ReflectionAnnotation.Reflection.Person");
//获取到Person的空参构造方法
Constructor con = c.getConstructor(null);
//执行构造方法创建对象
Object obj = con.newInstance();
System.out.println(obj);
//获取到Person的私有构造方法
Constructor con2 = c.getDeclaredConstructor(String.class,Integer.class);
//取消访问控制
con2.setAccessible(true);
Object obj2 = con2.newInstance("张三",24);
System.out.println(obj2);
}
运行结果:
四、获取成员变量
1、获取成员变量
public static void main(String[] args) throws ClassNotFoundException {
//获取Person的字节码对象
Class c = Class.forName("csdn.ReflectionAnnotation.Reflection.Person");
//获取成员变量
Field[] fs = c.getFields();//所有的public成员变量
for(Field f : fs){
System.out.println(f);
}
System.out.println("-------------------------------------");
//所有成员变量
Field[] fs1 = c.getDeclaredFields();
for(Field f : fs1){
System.out.println(f);
}
}
运行结果:
2、获取和设置成员变量
public static void main(String[] args) throws Exception {
//1、获取Person的字节码对象
Class c = Class.forName("csdn.ReflectionAnnotation.Reflection.Person");
//2、获取构造方法
Constructor con = c.getDeclaredConstructor(String.class,Integer.class);
//3、取消访问限制
con.setAccessible(true);
//4、执行构造方法创建对象
Object obj = con.newInstance("李四",35);
//5、获取成员变量
Field f1 = c.getField("address");
//6、给address赋值
f1.set(obj,"北京");
//7、取出address的值
System.out.println(f1.get(obj));
//8、获取name和age的值
Field f2 = c.getDeclaredField("name");
f2.setAccessible(true);//接触访问限制
//获取name的值
System.out.println(f2.get(obj));
}
运行结果:
五、获取方法和执行方法
首先,先在 Person 类中增加两个方法
public void method1(){
System.out.println("method1");
}
public void method2(String msg){
System.out.println(msg);
}
private void method3(){ //注意,method3为私有方法
System.out.println("method3");
}
1、获取方法
public static void main(String[] args) throws Exception{
Class c = Class.forName("csdn.ReflectionAnnotation.Reflection.Person");
Method[] methods1 = c.getMethods();//获取Person类所有public方法
Method[] methods2 = c.getDeclaredMethods();//获取Person类所有方法
/* for(Method method : methods2){
System.out.println(method);
}*/
Method m1 = c.getMethod("method1",null);
System.out.println(m1);
Method m2 = c.getMethod("method2", String.class);
System.out.println(m2);
}
运行结果:
注释掉的部分你可以自己尝试一下运行结果。
2、通过反射创建对象并且执行方法
public static void main(String[] args) throws Exception{
Class c = Class.forName("csdn.ReflectionAnnotation.Reflection.Person");
Constructor con = c.getConstructor(null);//获取空参的构造方法
Object obj = con.newInstance(null);
Method m1 = c.getMethod("method1",null);
m1.invoke(obj,null);//执行无参数的方法
Method m2 = c.getMethod("method2", String.class);
m2.invoke(obj,"hello");
Method m3 = c.getDeclaredMethod("method3",null);//获取私有方法
m3.setAccessible(true);//取消访问限制
m3.invoke(obj,null);
}
运行结果:(在隔离没明白可以看总结)
六、 泛型擦除
将已存在的 ArrayList 集合中添加一个字符串数据,那么就可以使用反射,你就可以向这个集合中添加任意元素。(泛型用来规定集合只能存储某一种类型的数据,真™是一个 奇奇怪怪的设定)
public static void main(String[] args) throws Exception {
ArrayList<Integer> arr = new ArrayList<Integer>();
arr.add(3);
arr.add(5);
arr.add(7);
// arr.add("hello");
Class c = Class.forName("java.util.ArrayList");
Method m = c.getMethod("add",Object.class);
m.invoke(arr,"hello");
System.out.println(arr);
}
运行结果:
七、反射配置文件
在包内新建一个 .txt 文件,(我的文件名为 people.txt )文件内容为:
className=csdn.ReflectionAnnotation.Reflection.Person
methodName=method1
public static void main(String[] args) throws Exception {
//在文件中读取类名和方法名
Properties prop = new Properties();
prop.load(new FileInputStream("C:\\Users\\86139\\Desktop\\untitled\\src\\csdn\\ReflectionAnnotation\\people.txt"));
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
Class c = Class.forName(className);
Constructor con = c.getConstructor(null);
Object obj = con.newInstance(null);
Method m = c.getMethod(methodName,null);
m.invoke(obj,null);
}
那个路径要填对,不然会抛出异常。运行结果:
总结
1、异常太多了,所以直接抛出 Exception 就好了。
2、创建对象的时候会自动调用无参的构造方法,所以会执行无参构造方法里面的内容
好了,大概就这么多吧,全是代码毫无感情。