一、通过例子引入反射
/** 反射案例:
* 实现美团外卖的支付功能:
* 1.微信,支付宝,各大银行卡 来实现支付
* 2.顾客选择支付方式!
*实现步骤:
* (1).创建美团接口,支付方法
* (2).创建实现类 完成方法的重写
* (3).创建测试类,完成流程
*/
【接口:】
/**
* 美团外卖 支付接口!
*
*/
public interface MTWM {
void onlinePayment();
}
【实现类:】
/**
* 微信 实现支付方式
*/
public class WeChat implements MTWM {
@Override
public void onlinePayment() {
System.out.println("正在使用微信 进行支付。。。");
}
}
public class Ali implements MTWM {
@Override
public void onlinePayment() {
System.out.println("支付宝 正在进行 支付操作。。。。");
}
}
public class BanCard implements MTWM {
@Override
public void onlinePayment() {
System.out.println("正在使用银行卡 进行支付操作。。。");
}
}
【测试类】
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
//提示用户,选择哪种支付方式:
Scanner input=new Scanner(System.in);
System.out.println("请选择支付方式:1.微信,2.支付宝,3.银行卡.....");
/* int i=input.nextInt();
if(i==1){
WeChat weChat=new WeChat();
pay(weChat);
}else if(i==2){
Ali ali=new Ali();
pay(ali);
}else if(i==3){
BanCard banCard=new BanCard();
pay(banCard);
}*/
String str=input.next();
Class c=Class.forName(str);
Object o=c.newInstance();
Method method=c.getDeclaredMethod("onlinePayment");
method.invoke(o);
}
public static void pay( MTWM mtwm){
mtwm.onlinePayment();
}
/*
public static void pay( WeChat weChat){
weChat.onlinePayment();
}
public static void pay( Ali ali){
ali.onlinePayment();
}
public static void pay( BanCard banCard){
banCard.onlinePayment();
}
*/
运行结果如下:
二、简单介绍反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
补充:
动态语言vs静态语言
1、动态语言
动态语言是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。
主要动态语言: Object-C、 C#、JavaScript、 PHP、 Python、 Erlang 。
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++。
Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!
三、获得Class对象的四种方式
/**
*第一种:通过对象名.getClass()获得
*/
Student student=new Student();
Class cla=student.getClass();
/**
*第二种:直接Class.forName()获得
*/
Class cla02=Class.forName("com.demo02.Student");
/**
*第三种:通过类名.class获得
*/
Class cla03=Student.class;
/**
*第四种:通过classLoader.loadClass()获得
*/
ClassLoader classLoader= Test.class.getClassLoader();
Class cla04=classLoader.loadClass("com.demo02.Student");
四、获得构造器、创建对象
//获得构造器,并通过构造器创建对象:
public static void getconstructor() throws
ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
InvocationTargetException, InstantiationException {
//1.获得Class 字节码文件对象:
Class c=Class.forName("com.demo02.Student");
//2.获得字节码文件里【公有】的构造器:
Constructor[] constructors= c.getConstructors();
for(Constructor constructor:constructors){
System.out.println(constructor);
}
System.out.println("==========");
//2.2获得字节码文件里【所有】的构造器:
Constructor[] constructors1= c.getDeclaredConstructors();
for(Constructor constructor:constructors1){
System.out.println(constructor);
}
//2.3 获得字节码文件里【某一个】构造器: 有参构造器
Constructor constructor= c.getDeclaredConstructor
(String.class,String.class,String.class,double.class);
Student stu=(Student)constructor.newInstance("3班","java","长春大学",178);
System.out.println(stu);
//无参构造器
Constructor constructor01= c.getDeclaredConstructor();
Student stu02=(Student)constructor01.newInstance();
System.out.println(stu02);
}
五、获得属性、对属性进行取值/赋值
public static void getField01() throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.获得字节码文件对象:
Class c=Student.class;
//2.获得属性:
//Field[] fields=c.getFields(); //获得当前类+父类里所有的public 修饰的属性
Field[] fields= c.getDeclaredFields();//获得当前类所有的属性
//c.getField(); //根据参数 属性名--》获得当前类+父类里某一个public 修饰的属性
// c.getDeclaredField();//根据参数 属性名--》得当前类+父类里某一个属性
for (Field field :fields){
System.out.println("属性名:"+field.getName());
System.out.println("属性类型:"+field.getType());
System.out.println("属性修饰符:"+field.getModifiers());
}
//3.给属性赋值:
Field field= c.getField("heigth");
Student stu=(Student)c.getConstructor().newInstance(); //无参构造
field.setDouble(stu,176.5);
System.out.println(stu);
}
六、获得行为方法并执行方法
public static void getMethod01() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.获得字节码文件对象:
Student stu=new Student();
Class c=stu.getClass();
//2.获得方法:
Method[] methods=c.getMethods();//获得当前类+父类中所有public方法;
/* for(Method method:methods){
System.out.println(method);
}*/
//2.2
Method[] methods02=c.getDeclaredMethods(); //获得本类下的所有方法
for(Method method:methods02){
System.out.println(method);
}
//3.执行方法:
//调用 protected,有参的
Method method=c.getDeclaredMethod("method02",String.class,int.class);
System.out.println(method.invoke(stu,"张三",90));
//调用public,有参:
Method method1=c.getMethod("method01",int.class);
method1.invoke(stu,100);
}
七、私有资源调用
通过暴力反射,不让检查属性的权限来调用!
public static void usePrivate() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
//1.获得Class字节码文件对象:
Class c=Test.class.getClassLoader().loadClass("com.demo02.Student");
//2.获得私有构造器,同时创建对象:
Constructor constructor= c.getDeclaredConstructor(String.class);
constructor.setAccessible(true);//暴力反射,不让检查构造器的权限!
Student stu=(Student)constructor.newInstance("张三");
//3.获得私有属性,给属性赋值:
Field field=c.getDeclaredField("stuid");
field.setAccessible(true);//暴力反射,不让检查属性的权限!
field.set(stu,"10-02");
//4.获得私有方法,同时调用:
Method method=c.getDeclaredMethod("method02",int.class);
method.setAccessible(true);//暴力反射,不让检查方法的权限!
method.invoke(stu,99);
System.out.println(stu);
}
八、获得接口和父类
public static void getSuper01(){
Class c=Student.class;
Class superClass=c.getSuperclass(); //获得父类
Field[] fields=superClass.getDeclaredFields(); //获得父类所有方法
for(Field field:fields){
System.out.println(field);
}
}
九、泛型集合
public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, NoSuchFieldException {
ArrayList<Integer> list=new ArrayList<>();
list.add(90); //泛型只存在于编译期
//1.获得ArrayList的字节码文件对象:
Class c=Class.forName("java.util.ArrayList");
//2.调用方法:
Method method= c.getMethod("add",Object.class);
System.out.println(method);
method.invoke(list,"zhangsan");
System.out.println(list.size());
}