Java基础-反射(重中之重)

反射是框架灵魂的起源

 反射是通过字节码文件(.class)获得类中的属性、方法、构造方法

使用到的Person类

 1 public class Person {
 2     private String name;
 3     protected int age;
 4     String sex;
 5     public String hobby;
 6 
 7     public Person() {
 8 
 9     }
10 
11     protected Person(String name) {
12         this.name = name;
13     }
14 
15     Person(String name, int age) {
16         this.name = name;
17         this.age = age;
18     }
19 
20     private Person(String name, int age, String sex, String hobby) {
21         this.name = name;
22         this.age = age;
23         this.sex = sex;
24         this.hobby = hobby;
25     }
26 
27     private void show() {
28         System.out.println("我是一个私有无返回值的方法");
29     }
30 
31     protected void show(double money) {
32         System.out.println(this.name + "有巨额资产" + money + "元");
33     }
34 
35     int show(int i, int j) {
36         return i * j;
37     }
38 
39     public double show(double i, double j, double k) {
40         return i * j - k;
41     }
42 
43     public String getName() {
44         return name;
45     }
46 
47     public void setName(String name) {
48         this.name = name;
49     }
50 
51     public int getAge() {
52         return age;
53     }
54 
55     public void setAge(int age) {
56         this.age = age;
57     }
58 
59     public String getSex() {
60         return sex;
61     }
62 
63     public void setSex(String sex) {
64         this.sex = sex;
65     }
66 
67     public String getHobby() {
68         return hobby;
69     }
70 
71     public void setHobby(String hobby) {
72         this.hobby = hobby;
73     }
74 
75     @Override
76     public String toString() {
77         return "Person{" +
78                 "name='" + name + '\'' +
79                 ", age=" + age +
80                 ", sex='" + sex + '\'' +
81                 ", hobby='" + hobby + '\'' +
82                 '}';
83     }
84 }

 

动态加载字节码文件的三种方法

 1 public class createClass {
 2     public static void main(String[] args) {
 3         //方法一:类.class
 4         Class class1 = Person.class;
 5 
 6         //方法二:类.getClass
 7         Person person = new Person("阿水");
 8         Class class2 = person.getClass();
 9         System.out.println("class1是否和class2相等 " + class1.equals(class2));
10 
11         //方法三:class.forName(String pathName) pathName 类的路径名
12         //方法三在平时使用中常用,结合配置文件可以提高程序的耦合性和灵活性
13         try {
14             Class class3 = Class.forName("com.company.ReflectDemo.Person");
15             System.out.println("class1是否和class3相等 " + class1.equals(class3));
16         } catch (ClassNotFoundException e) {
17             e.printStackTrace();
18         }
19     }
20 }

代码运行如下:

 

1     class1是否和class2相等 true
2     class1是否和class3相等 true

 

 

 

访问和使用构造方法

 1 public class getConstructor {
 2     /**
 3      * 获取指定的构造方法
 4      *  Constructor constructor = clazz.getConstructor(传入参数类型例如 String.class);    只能获得公有的构造方法
 5      *  Constructor constructor = clazz.getDeclaredConstructor(传入参数类型例如 String.class);  可以获得私有、受保护、默认、公有的构造方法
 6      *
 7      * 获得全部的构造方法
 8      *  Constructor[] constructor = clazz.getConstructors();    只能获得公有的构造方法
 9      *  Constructor[] constructor = clazz.getDeclaredConstructors(); 可以获得私有、受保护、默认、公有的构造方法
10      */
11     public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
12         Class clazz = Class.forName("com.company.ReflectDemo.Person");
13         //获得所有的构造方法
14         Constructor[] constructors = clazz.getDeclaredConstructors();
15         for (Constructor constructor : constructors) {
16             StringBuffer str = new StringBuffer();  //StringBuffer效率比较高
17             //getModifiers()返回是int类型,我们要得到访问修饰符 就需要将拿到的访问修饰符的等级放入Modifier.toString()中
18             str.append(Modifier.toString(constructor.getModifiers()) + " ");
19             str.append(constructor.getName() + " (");
20             Parameter[] params = constructor.getParameters();   //参数个数不止一个
21             for (Parameter parameter : params) {
22                 str.append(parameter.getType() + " ");
23                 str.append(parameter.getName() + " ,");
24             }
25             if(str.toString().endsWith(",")){   //用来去掉多余的,
26                 str.replace(str.length() - 1,str.length(),"");
27             }
28             str.append(")");
29             System.out.println(str);
30         }
31         System.out.println("=======================================================================================");
32         //使用其中的一个构造方法来创建一个对象
33         //使用这个构造方法 private Person(String name, int age, String sex, String hobby)
34         //使用某个具体的构造方法时,clazz.getDeclaredConstructor(这里传入对应个数和类型的.class)
35         Constructor constructor = clazz.getDeclaredConstructor(String.class,int.class,String.class,String.class);
36         constructor.setAccessible(true);//关闭安全检测
37         //我们在开发中大都用Object接受反射创建的对象
38         //constructor.newInstance(传入对应的实例化对象的值) 这一句就相当于 Person p1 = new Person("阿水",21,"男","爱好很广泛");
39         Object objPerson = constructor.newInstance("阿水",21,"男","爱好很广泛");
40         constructor.setAccessible(false);//使用完毕需要关闭
41         System.out.println((Person)objPerson);
42     }
43 }

代码运行如下:

1   public com.company.ReflectDemo.Person ()
2   private com.company.ReflectDemo.Person (class java.lang.String arg0 ,int arg1 ,class java.lang.String arg2 ,class java.lang.String arg3 )
3    com.company.ReflectDemo.Person (class java.lang.String arg0 ,int arg1 )
4   protected com.company.ReflectDemo.Person (class java.lang.String arg0 )
5   =======================================================================================
6   Person{name='阿水', age=21, sex='男', hobby='爱好很广泛'}

 

访问和使用成员变量

 1 public class getField {
 2     /**
 3      * 获得指定的成员变量
 4      * Field fields = clazz.getField(); 只能获得公共的成员变量
 5      * Field fields = clazz.getDeclaredField(); 可以获得私有、受保护、默认、公有的成员变量
 6      *
 7      * 获得全部成员变量
 8      * Field[] fields = clazz.getFields();  只能获得所有公共的成员变量
 9      * Field[] fields = clazz.getDeclaredFields();  可以获得所有私有、受保护、默认、公有的成员变量
10      *
11      */
12     public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
13         Class clazz = Class.forName("com.company.ReflectDemo.Person");
14         //获得所有的参数
15         Field[] fields = clazz.getDeclaredFields();
16         for (Field field : fields) {
17             StringBuffer str = new StringBuffer();
18             //getModifiers()返回是int类型,我们要得到访问修饰符 就需要将拿到的访问修饰符的等级放入Modifier.toString()中
19             str.append(Modifier.toString(field.getModifiers()) + " ");
20             str.append(field.getName());
21             System.out.println(str);
22         }
23         System.out.println("=======================================================================================");
24         //获得成员变量,并且进行赋值
25         Object ObjPerson = clazz.getConstructor().newInstance();
26         //如下注释的方法也可以 判断的写法可以在不明确类中是否存在此变量时使用
27 //        for (Field field : fields) {
28 //            //通过equal方法来判断进行赋值
29 //            field.setAccessible(true);  //关闭安全检测(这里没有写错 true是关闭 false是开启)
30 //            if("sex".equals(field.getName())){
31 //                field.set(ObjPerson,"男");
32 //            }else if("age".equals(field.getName())){
33 //                field.set(ObjPerson,21);
34 //            }else if("name".equals(field.getName())){
35 //                field.set(ObjPerson,"阿水");
36 //            }else if("hobby".equals(field.getName())){
37 //                field.set(ObjPerson,"爱好广泛");
38 //            }
39 //            field.setAccessible(false);//使用完毕需要关闭
40 //        }
41 
42         Field field = clazz.getDeclaredField("name");
43         field.setAccessible(true);//关闭安全检查
44         field.set(ObjPerson,"阿水");
45         field = clazz.getDeclaredField("sex");
46         field.set(ObjPerson,"男");
47         field = clazz.getDeclaredField("age");
48         field.set(ObjPerson,21);
49         field = clazz.getDeclaredField("hobby");
50         field.set(ObjPerson,"爱好广泛");
51         field.setAccessible(false);//用完打开安全检测
52         System.out.println((Person)ObjPerson);
53     }
54 }

代码运行如下:

1   private name
2   protected age
3    sex
4   public hobby
5   =======================================================================================
6   Person{name='阿水', age=21, sex='男', hobby='爱好广泛'}

 

访问和使用方法

 1 public class getMethod {
 2     /**
 3      * 获得指定的方法
 4      * Method method = clazz.getMethod();   只能获得公共的方法
 5      * Method method = clazz.getDeclaredMethod();   可以获得私有、受保护、默认、公有的方法
 6      *
 7      * 获得全部方法
 8      * Method[] method = clazz.getMethods();    只能获得所有公共的方法
 9      * Method[] method = clazz.getDeclaredMethods();    可以获得所有私有、受保护、默认、公有的方法
10      *
11      *
12      */
13     public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
14         Class clazz = Class.forName("com.company.ReflectDemo.Person");
15         //获得所有的方法
16         Method[] methods = clazz.getDeclaredMethods();
17         for (Method method : methods) {
18             StringBuffer str = new StringBuffer();
19             str.append(Modifier.toString(method.getModifiers()) + " ");
20             str.append(method.getReturnType() + " ");
21             str.append(method.getName() + "(");
22             Parameter[] params = method.getParameters();
23             for (Parameter param : params) {
24                 str.append(param.getType().getSimpleName() + " ");
25                 str.append(param.getName() + " ,");
26             }
27             if(str.toString().endsWith(",")){   //去掉多余的,
28                 str.replace(str.length() - 1,str.length(),"");
29             }
30             str.append(")");
31             System.out.println(str);
32         }
33         System.out.println("=======================================================================================");
34         //使用方法 public double show(double i, double j, double k) i * j - k
35         Method method = clazz.getDeclaredMethod("show",double.class,double.class,double.class);
36         Object objPerson = clazz.getConstructor().newInstance();
37         Object val = method.invoke(objPerson,2.5,4.0,3.0);
38         System.out.println((double)val);
39     }
40 }

代码运行如下:

 1   public class java.lang.String getName()
 2   public class java.lang.String toString()
 3   public void setName(String arg0 )
 4   public void setAge(int arg0 )
 5   public void setSex(String arg0 )
 6   public class java.lang.String getSex()
 7   public class java.lang.String getHobby()
 8   public int getAge()
 9   public void setHobby(String arg0 )
10    int show(int arg0 ,int arg1 )
11   public double show(double arg0 ,double arg1 ,double arg2 )
12   protected void show(double arg0 )
13   private void show()
14   =======================================================================================
15   7.0

 

工厂模式+配置文件+反射的小练习

Hero抽象类(英雄的父类)

 1 public abstract class Hero {
 2     private String name;
 3     private String speak;
 4 
 5     public Hero() {
 6 
 7     }
 8 
 9     public abstract void fightShow();
10 
11 
12     public String getName() {
13         return name;
14     }
15 
16     public void setName(String name) {
17         this.name = name;
18     }
19 
20     public String getSpeak() {
21         return speak;
22     }
23 
24     public void setSpeak(String speak) {
25         this.speak = speak;
26     }
27 
28     @Override
29     public String toString() {
30         return "Hero{" +
31                 "name='" + name + '\'' +
32                 ", speak='" + speak + '\'' +
33                 '}';
34     }
35 }

法师类(继承了Hero)

 1 public class Master extends Hero{
 2     public Master(String name, String speak) {
 3         setName(name);
 4         setSpeak(speak);
 5     }
 6     @Override
 7     public void fightShow() {
 8         System.out.println(this.getName() + "说:" + this.getSpeak());
 9     }
10 }

战士类(继承了Hero)

 1 public class Warrior extends Hero{
 2     public Warrior(String name, String speak) {
 3         setName(name);
 4         setSpeak(speak);
 5     }
 6     @Override
 7     public void fightShow() {
 8         System.out.println(this.getName() + "说:" + this.getSpeak());
 9     }
10 }

英雄工厂类

 1 public class HeroFactory {
 2     //配置文件
 3     private static Properties pros = new Properties();
 4     static{
 5         try {
 6             //先将配置文件加载进入内存 类名.class.getClassLoader().getResourceAsStream() 使用类加载器加载本类和配置文件中的内容进入内存
 7             pros.load(HeroFactory.class.getClassLoader().getResourceAsStream("com/company/ReflectFactoryDemo/hero.properties"));
 8         } catch (IOException e) {
 9             e.printStackTrace();
10         }
11     }
12     public static <T>T getHero(String heroTypeName,Object[] objects){
13         Class clazz = null;
14         try {
15             //根据用户传入的heroTypeName在配置文件中找关联映射(配置文件是键值对的形式)
16             clazz = Class.forName(pros.getProperty(heroTypeName));
17             Constructor constructor = clazz.getDeclaredConstructor(String.class,String.class);
18             //返回创建出的实例对象
19             return (T)constructor.newInstance(objects[0],objects[1]);
20         } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
21             e.printStackTrace();
22         }
23         return null;
24     }
25 }

角斗场类

 1 public class HeroBattleField {
 2     /**
 3      * 传入两个英雄,模拟对战,输出各自的口头禅
 4      * @param hero1
 5      * @param hero2
 6      */
 7     public static void show(Hero hero1,Hero hero2){
 8         hero1.fightShow();
 9         hero2.fightShow();
10     }
11 }

测试类

1 public class Test {
2     public static void main(String[] args) {
3         Hero warrior = (Hero) HeroFactory.getHero("warrior",new Object[]{"幻影长矛手","杀了孙行者,还有者行孙"});
4         Hero master = (Hero) HeroFactory.getHero("master",new Object[]{"拉比克","读书人的事情,怎能算偷,这是借"});
5         HeroBattleField.show(warrior,master);
6     }
7 }

代码运行如下:

1   幻影长矛手说:杀了孙行者,还有者行孙
2   拉比克说:读书人的事情,怎能算偷,这是借

 

posted @ 2021-01-17 20:40  阿水弟弟  阅读(85)  评论(0)    收藏  举报