JAVA反射之绕过编译阶段&&做企业级通用框架

反射的作用:绕过编译阶段为集合添加数据

  • 反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素的。
  • 泛型只是在编译阶段可以约束集合只能操作某种数据类型,例如:ArrayList<Integer>list=new ArrayList<>();在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。

 小案例:

import java.lang.reflect.Method;
import java.util.ArrayList;

public class 反射机制_3绕过编译 {
    public static void main(String[] args) throws Exception {
        //反射实现泛型擦除后,加入其他类型的元素
        ArrayList<String> list1=new ArrayList<>();
        ArrayList<Integer> list2=new ArrayList<>();

        System.out.println(list1.getClass());
        System.out.println(list2.getClass());

        System.out.println(list1.getClass()==list2.getClass());//可以发现泛型被擦除了,都是ArrayList类型的了
        System.out.println("--------------------------------");
        ArrayList<Integer> list3=new ArrayList<>();
        list3.add(18);
        list3.add(20);
        //list3.add("遇安");类型与定义的类型不同,所以无法添加

        Class c=list3.getClass();//ArrayList.class ==>public boolean add(E e),此时的add方法没有受到类型约束,因为泛型被擦除了
        //定义c类中的add方法
        Method add=c.getDeclaredMethod("add",Object.class);
        boolean rs= (boolean) add.invoke(list3,"遇安");
        System.out.println(rs);
        System.out.println(list3);//运行结果:[18, 20, 遇安],我们可以发现定义的是Integer类型,但String类型照样被添加进去了

        //突破类型的另一种方法:
        ArrayList list4=list3;
        list4.add("欢迎");
        list4.add(false);
        System.out.println(list3);//运行结果:[18, 20, 遇安, 欢迎, false]
    }
}

 反射做通用框架:

需求:给你任意一个对象,在不清楚对象字段的情况下,可以把对象的字段名称和对应值存储到文件中去。

分析:

1、定义一个方法,可以接收任意类的对象

2、每次收到一个对象后,需要解析这个对象的全部成员变量名称

3、这个对象可能是任意的,那么怎么样才可以知道这个对象的全部成员变量名称呢?

4、使用反射获取对象的Class类对象,然后获得全部成员变量信息

5、遍历成员变量信息,然后提取本成员变量在对象中的具体值

6、存入成员变量名称和值到文件中去即可

 通用框架:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

//保存任意类型的对象
public class 反射_3通用框架 {
    public static void save(Object obj)  {
        try( PrintStream ps=new PrintStream(new FileOutputStream("存储的文件路径"));
        ) {
            //提取这个对象的全部成员变量,只有反射可以解决
            Class c=obj.getClass();//c.getSimpleName()获取当前类名 c.getName()获取全限名:包名+类名
            ps.println("====="+c.getSimpleName()+"=====");//可以知道当前保存的是哪个类的数据
            //提取它的全部成员变量
            Field []fields=c.getDeclaredFields();
            //获取成员变量的信息
            for (Field field : fields) {
                String name=field.getName();
                //提取本成员变量在obj对象中的值(取值)
                field.setAccessible(true);
                String value=field.get(obj)+"";//因为最后是要存到文件中去的,所以都用的String
                ps.println(name+"="+value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

 反射的作用:

  • 可以在运行时得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 也可以破坏泛型的约束性
  • 更重要的用途是适合做Java高级框架

猜你喜欢

转载自blog.csdn.net/qq_62731133/article/details/125135991