反射
多态:父类做参数====扩展效果好
父类做返回值====方法体内部是使用if选择判断,方法体仍然需要修改!
====解决方式:反射!
一,例子{初步感受}
美团外卖,支付例子:
下单支付的时候,可以选择微信支付,支付宝支付,吉林银行,北京银行。。。。
继承:抽象父类 支付方法
微信 支付宝 银行
美团下单: 传入用户的选择,创建对应的对象,调用支付方法。
-
Fsther类
package com.jr.reflect.demo1; public abstract class Father { public abstract void payOnLine(); }
-
Ali类
package com.jr.reflect.demo1; public class Ali extends Father { @Override public void payOnLine() { System.out.println("使用支付宝 完成支付功能!"); } }
-
WeChat类
package com.jr.reflect.demo1; public class WeChat extends Father { @Override public void payOnLine() { System.out.println("使用微信完成,支付功能,本单省去0.10元"); } }
-
JLBank类
package com.jr.reflect.demo1; public class JLBank extends Father { @Override public void payOnLine() { System.out.println("使用吉林银行支付,本次消费打折0.95"); } }
-
BJBank类
package com.jr.reflect.demo1; public class BJBank extends Father { @Override public void payOnLine() { System.out.println("使用北京银行,完成支付!"); } }
-
MTWM类
package com.jr.reflect.demo1; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class MTWM { /* public void placeAnOrder(String str){ if (str.equals("微信")) { new WeChat().payOnLine(); }else if(str.equals("支付宝")){ new Ali().payOnLine(); }else{ new JLBank().payOnLine(); } }*/ public void placeAnOrder(String str) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class aClass = Class.forName(str); Object o = aClass.newInstance(); Method payOnLine = aClass.getMethod("payOnLine"); payOnLine.invoke(o); //反射学习的内容:学习如何获得构造方法,如何通过构造创建对象,如何获得属性,如何为属性赋值;如何获得方法,如何调用方法。 } }
-
Text类
package com.jr.reflect.demo1; import java.lang.reflect.InvocationTargetException; import java.util.Scanner; public class Test { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { MTWM mtwm = new MTWM(); System.out.println("请输入你的支付方式:"); String str = new Scanner(System.in).next(); mtwm.placeAnOrder(str); } }
二,反射学习的内容
Person类(属性准备)
package reflection.demo;
public class Person {
private String idCard;
private String name;
private Integer age;
public Person() {
System.out.println("Person类的无参构造");
}
public Person(String idCard, String name, Integer age) {
this.idCard = idCard;
this.name = name;
this.age = age;
System.out.println("Person类的有参构造");
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
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;
}
protected void show() {
System.out.println("无参方法---我是人类:身份证号是:" + idCard
+ "姓名是:" + name + "年龄是" + age);
}
protected void show(String idCard, String name, Integer age) {
System.out.println("有参方法---我是人类:身份证号是:" + idCard
+ "姓名是:" + name + "年龄是" + age);
}
@Override
public String toString() {
return "Person{" +
"idCard='" + idCard + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
1.获得字节码文件对象的方式:
(1)从源文件的角度,使用对象
public static void main1(String[] args) {
//从源文件的角度,使用对象
Person person=new Person();
person.setAge(23);
person.show();
System.out.println(person);
}
(2)从字节码文件的角度,使用对象
-
通过路径的方式 获得字节码文件对象:
-
通过类名 获得字节码文件对象:
-
通过对象名 获得字节码文件对象:
-
通过类加载器,加载指定路径字节码文件, 获得文件对象:
public static void main2(String[] args) throws ClassNotFoundException {
//从字节码文件的角度,使用对象
//1.通过路径的方式 获得字节码文件对象:
Class class1 = Class.forName("com.jr.reflect.demo2.Person");//字节码文件在当前项目里的唯一位置:全局限定名 就是包名.类名
//2.通过类名 获得字节码文件对象:
Class class2= Person.class;
//3.通过对象名 获得字节码文件对象:
Person person=new Person();
Class class3 = person.getClass();
//4.通过类加载器,加载指定路径字节码文件, 获得文件对象:
ClassLoader classLoader = Test1.class.getClassLoader();
Class class4= classLoader.loadClass("com.jr.reflect.demo2.Person");
System.out.println(class1==class2);
System.out.println(class2==class3);
System.out.println(class3==class4);
}
2.如何获得构造方法,如何通过构造创建对象
- 执行单个构造方法
- 通过构造方法,实例化对象
- 输出对象
public static void main3(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class cla=Class.forName("reflection.demo.Person");
Constructor[] constructors=cla.getConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
//执行单个构造方法
Constructor constructor=cla.getConstructor();
//通过构造方法,实例化对象
Object o=constructor.newInstance();
//输出对象
System.out.println(o);
Constructor constructor1=cla.getConstructor(String.class,String.class,Integer.class);
Object zs=constructor1.newInstance("123456789","张丹",34);
System.out.println(zs);
}
3.如何获得属性,如何为属性赋值;
public static void main4(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
//拿全部
Class<?> cla = Class.forName("reflection.demo.Person");
//Field[] fields = cla.getFields(); //只获得public修饰的属性
Field[] fields = cla.getDeclaredFields();//只要是声明的属性都获得!
for (Field f : fields) {
System.out.println(f);
}
//拿单个
Object o=cla.newInstance();
Field name = cla.getDeclaredField("name");
name.setAccessible(true);//暴力访问,不推荐使用(对象不是私有就不需要)
name.set(o,"李四");
System.out.println(o);
Field idCard = cla.getDeclaredField("idCard");
idCard.setAccessible(true);
idCard.set(o,"123456789");
System.out.println(o);
Field age = cla.getDeclaredField("age");
age.setAccessible(true);
age.set(o,12);
System.out.println(o);
}
4.如何获得方法,如何调用方法。
public static void main5(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
//拿字节码文件
//拿全部 --数组
Class<?> cla = Class.forName("reflection.demo.Person");
Method[] methods = cla.getMethods();
for (Method m : methods) {
System.out.println(m);
}
//拿单个 --- 无参
Method show = cla.getDeclaredMethod("show");
show.invoke(cla.newInstance());
//---有参
Method show1 = cla.getDeclaredMethod("show",String.class,String.class,String.class);
show1.invoke(cla.newInstance(),"123456789","王五",42);
}
5.反射 破 泛型集合:
泛型集合:只存在程序编译期,程序运行时没有泛型集合。
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
/* ArrayList<String> list=new ArrayList<>();
list.add("zhangsan");
list.add("李四");
list.add(34);
System.out.println(list.size());*/
Class cla2= Class.forName("java.util.ArrayList");
Object list = cla2.newInstance();
Method add = cla2.getDeclaredMethod("add", Object.class);
add.invoke(list,"张三");
add.invoke(list,"李四");
add.invoke(list,34);
add.invoke(list,true);
Method size = cla2.getDeclaredMethod("size");
System.out.println(size.invoke(list));
System.out.println(list);
}