JavaSE大神进阶篇(第九期):反射机制体现动态编程的强大利器
·
通过案例体会反射的好处
-
案例:美团外卖 —> 付款 —> 要么用微信支付 要么用支付宝支付
-
代码展示:
package com.xxx.test01; //接口的制定方:美团外卖 public interface Mtwm { //在线支付功能: void payOnline(); }public class WeChat implements Mtwm { @Override public void payOnline() { //具体实现微信支付的功能: System.out.println("我已经点了外卖,正在使用微信支付"); } }public class AliPay implements Mtwm { @Override public void payOnline() { //具体的支付宝支付: System.out.println("我已经点了外卖,我正在使用支付宝进行支付"); } }public class BankCard implements Mtwm { @Override public void payOnline() { System.out.println("我已经定了外卖,我正在用招商银行信用卡支付"); } } -
测试类:
package com.zhaoss.test01; public class Test { public static void main(String[] args) { //定义一个字符串,用来模拟前台的支付方式: String str = "微信"; if("微信".equals(str)) { //str.equals("微信") ---?避免空指针异常 //微信支付: //new WeChat().payOnline(); pay(new WeChat()); } if("支付宝".equals(str)) { //支付宝支付: //new AliPay().payOnline(); pay(new AliPay()); } if("招商银行".equals(str)){ pay(new BankCard()); } } //微信支付 public static void pay(WeChat wc) { wc.payOnline(); } //支付宝支付 public static void pay(AliPay ap) { ap.payOnline(); } //招商银行支付 public static void pay(BankCard bc){ bc.payOnline(); } } -
为了提高代码的扩展性 —> 面向对象特性:多态:
package com.zhaoss.test01; public class Test { public static void main(String[] args) { //定义一个字符串,用来模拟前台的支付方式: String str = "微信"; if("微信".equals(str)) { //str.equals("微信")---?避免空指针异常 //微信支付: pay(new WeChat()); } if("支付宝".equals(str)) { //支付宝支付: pay(new AliPay()); } if("招商银行".equals(str)) { pay(new BankCard()); } } //方法形参是接口,具体传入的是接口的实现类的对象 ---> 多态的一种形式 public static void pay(Mtwm m) { m.payOnline(); } } //多态确实可以提高代码的扩展性,但是:扩展性没有达到最好 //怎么没有达到最好:上面的分支,还是需要手动的删除或者添加 //解决办法:反射机制 -
利用反射实现上述功能:
package com.zhaoss.test01; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Demo { public static void main(String[] args) throws Exception { //定义一个字符串,用来模拟前台的支付方式: String str = "com.zhaoss.test01.AliPay"; //字符串:实际上 --> 就是微信类的全限定路径 //下面的代码就是利用反射: Class cls = Class.forName(str); //cls --> Class类具体的对象 --> AliPay字节码信息 Object o = cls.newInstance(); Method method = cls.getMethod("payOnline"); method.invoke(o); } }
-
通过概念再体会反射
Class类的理解

提供丰富的类
-
代码展示
package com.zhaoss.test02; //作为一个父类 public class Person { //属性 private int age; public String name; //方法 private void eat(){ System.out.println("Person---eat"); } public void sleep(){ System.out.println("Person---sleep"); } }package com.zhaoss.test02; //Student作为子类 public class Student extends Person { //属性: private int sno; //学号 double height; //身高 protected double weight; //体重 public double score; //成绩 //方法: public String showInfo() { return "我是一名三好学生"; } private void work(){ System.out.println("我以后会找工作 --> 成为码农 程序员 程序猿 程序媛"); } //构造器 public Student(){ System.out.println("空参构造器"); } private Student(int sno) { this.sno = sno; } Student(int sno, double weight) { this.sno = sno; this.weight = weight; } }
获取字节码信息的四种形式
-
代码展示
package com.zhaoss.test02; public class Test { public static void main(String[] args) throws ClassNotFoundException { //案例:以Person的字节码信息为案例 //方式1:通过getClass()方法获取 Person p = new Person(); Class c1 = p.getClass(); System.out.println(c1); //方式2:通过内置class属性: Class c2 = Person.class; System.out.println(c2); System.out.println(c1 == c2); //注意:方式1和方式2 不常用 //方式3:用的最多:调用Class类提供的静态方法forName Class c3 = Class.forName("com.zhaoss.test02.Person"); //方式4:利用类的加载器(了解技能点) ClassLoader loader = Test.class.getClassLoader(); Class c4 = loader.loadClass("com.zhaoss.test02.Person"); } }
可以作为Class类的实例的种类
-
Class类的具体的实例:
-
验证:
package com.zhaoss.test02; public class Demo { public static void main(String[] args) { /* Class类的具体的实例: (1)类:外部类,内部类 (2)接口 (3)注解 (4)数组 (5)基本数据类型 (6)void */ Class c1 = Person.class; Class c2 = Comparable.class; Class c3 = Override.class; int[] arr1 = {1,2,3}; Class c4 = arr1.getClass(); int[] arr2 = {5,6,7}; Class c5 = arr2.getClass(); System.out.println(c4 == c5); //结果:true .同一个维度,同一个元素类型,得到的字节码就是同一个 Class c6 = int.class; Class c7 = void.class; } }
获取运行时类的完整结构
-
补充完善上面提供的丰富的类
-
代码
//作为一个父类 public class Person implements Serializable { //属性 private int age; public String name; //方法 private void eat(){ System.out.println("Person---eat"); } public void sleep(){ System.out.println("Person---sleep"); } }package com.zhaoss.test03; //Student作为子类 @MyAnnotation(value="hello") public class Student extends Person implements MyInterface{ //属性: private int sno; //学号 double height; //身高 protected double weight; //体重 public double score; //成绩 //方法: @MyAnnotation(value="himethod") public String showInfo(){ return "我是一名三好学生"; } public String showInfo(int a, int b){ return "重载方法 ==== 我是一名三好学生"; } private void work(){ System.out.println("我以后会找工作 --> 成为码农 程序员 程序猿 程序媛"); } void happy(){ System.out.println("做人最重要的就是开心每一天"); } protected int getSno(){ return sno; } //构造器 public Student(){ System.out.println("空参构造器"); } private Student(int sno){ this.sno = sno; } Student(int sno, double weight){ this.sno = sno; this.weight = weight; } protected Student(int sno, double height, double weight){ this.sno = sno; } @Override @MyAnnotation(value="hellomyMethod") public void myMethod() { System.out.println("我重写了myMethod方法。。"); } @Override public String toString() { public String toString() { "sno=" + sno + ", height=" + height + ", weight=" + weight + ", score=" + score + '}'; } } }package com.zhaoss.test03; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.ElementType.LOCAL_VARIABLE; /* @Target:定义当前注解能够修饰程序中的哪些元素 @Retention:定义注解的声明周期 */ @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String value(); //属性 }package com.zhaoss.test03; public interface MyInterface { //自定义的接口 //随便定义一个抽象方法: void myMethod(); }
-
-
获取构造器和创建对象
-
代码展示
package com.zhaoss.test03; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Test01 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获取字节码信息: Class cls = Student.class; //通过字节码信息可以获取构造器: //getConstructors只能获取当前运行时类的被public修饰的构造器 Constructor[] c1 = cls.getConstructors(); for(Constructor c:c1){ System.out.println(c); } System.out.println("-------------------"); //getDeclaredConstructors: 获取运行时类的全部修饰符的构造器 Constructor[] c2 = cls.getDeclaredConstructors(); for(Constructor c:c2){ System.out.println(c); } System.out.println("-------------------"); //获取指定的构造器: //得到空构造器 Constructor con1 = cls.getConstructor(); System.out.println(con1); //得到两个参数的有参构造器: Constructor con2 = cls.getConstructor(double.class, double.class); System.out.println(con2); //得到一个参数的有参构造器:并且是private修饰的 Constructor con3 = cls.getDeclaredConstructor(int.class); System.out.println(con3); //有了构造器以后我就可以创建对象: Object o1 = con1.newInstance(); System.out.println(o1); Object o2 = con2.newInstance(180.5, 170.6); System.out.println(o2); } }
-
-
获取属性和对属性进行赋值
-
代码展示
package com.zhaoss.test03; import java.lang.reflect.Field; import java.lang.reflect.Modifier; public class Test02 { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException { //获取运行时类的字节码信息: Class cls = Student.class; //获取属性: //getFields:获取运行时类和父类中被public修饰的属性 Field[] fields = cls.getFields(); for(Field f:fields){ System.out.println(f); } System.out.println("---------------------"); //getDeclaredFields:获取运行时类中的所有属性 Field[] declaredFields = cls.getDeclaredFields(); for(Field f:declaredFields){ System.out.println(f); } System.out.println("---------------------"); //获取指定的属性: Field score = cls.getField("score"); System.out.println(score); Field sno = cls.getDeclaredField("sno"); System.out.println(sno); System.out.println("---------------------"); //属性的具体结构: //获取修饰符 /* int modifiers = sno.getModifiers(); System.out.println(modifiers); System.out.println(Modifier.toString(modifiers)); */ System.out.println(Modifier.toString(sno.getModifiers())); //获取属性的数据类型: Class clazz = sno.getType(); System.out.println(clazz.getName()); //获取属性的名字: String name = sno.getName(); System.out.println(name); System.out.println("-------------------------------"); //给属性赋值:(给属性设置值,必须要有对象) Field sco = cls.getField("score"); Object obj = cls.newInstance(); sco.set(obj,98); //给obj这个对象的score属性设置具体的值,这个值为98 System.out.println(obj); } }
-
-
获取方法和调用方法
-
代码展示
package com.zhaoss.test03; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class Test03 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException { //获取字节码信息: Class cls = Student.class; //获取方法: //getMethods: 获取运行时类的方法还有所有父类中的方法(被public修饰) Method[] methods = cls.getMethods(); for(Method m: methods){ System.out.println(m); } System.out.println("-----------------------"); //getDeclaredMethods: 获取运行时类中的所有方法: Method[] declaredMethods = cls.getDeclaredMethods(); for(Method m: declaredMethods){ System.out.println(m); } System.out.println("-----------------------"); //获取指定的方法: Method showInfo1 = cls.getMethod("showInfo"); System.out.println(showInfo1); Method showInfo2 = cls.getMethod("showInfo", int.class, int.class); System.out.println(showInfo2); Method work = cls.getDeclaredMethod("work", int.class); System.out.println(work); System.out.println("-----------------------"); //获取方法的具体结构: /* @注解 修饰符 返回值类型 方法名(参数列表) throws XXXXX{} */ //名字: System.out.println(work.getName()); //修饰符: int modifiers = work.getModifiers(); System.out.println(Modifier.toString(modifiers)); //返回值: System.out.println(work.getReturnType()); //参数列表: Class[] parameterTypes = work.getParameterTypes(); for(Class c: parameterTypes){ System.out.println(c); } //获取注解: Method myMethod = cls.getMethod("myMethod"); Annotation[] annotations = myMethod.getAnnotations(); for(Annotation a: annotations){ System.out.println(a); } //获取异常: Class[] exceptionTypes = myMethod.getExceptionTypes(); for(Class c: exceptionTypes){ System.out.println(c); } //调用方法: Object o = cls.newInstance(); myMethod.invoke(o); //调用o对象的mymethod方法 System.out.println(showInfo2.invoke(o,12,45));; } }
-
-
获取类的接口,所在包,注解
-
代码展示
package com.zhaoss.test03; import java.lang.annotation.Annotation; public class Test04 { public static void main(String[] args) { //获取字节码信息: Class cls = Student.class; //获取运行时类的接口: Class[] interfaces = cls.getInterfaces(); for(Class c: interfaces){ System.out.println(c); } //得到父类的接口: //先得到父类的字节码信息: Class superclass = cls.getSuperclass(); //得到接口: Class[] interfaces1 = superclass.getInterfaces(); for(Class c: interfaces1){ System.out.println(c); } //获取运行时类所在的包: Package aPackage = cls.getPackage(); System.out.println(aPackage); System.out.println(aPackage.getName()); //获取运行类的注解: Annotation[] annotations = cls.getAnnotations(); for(Annotation a: annotations){ System.out.println(a); } } }
-
-
关于反射的面试题
更多推荐


所有评论(0)