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 拉比克说:读书人的事情,怎能算偷,这是借

浙公网安备 33010602011771号