直接new对象就叫正射
如下
Map<String, String> map = new HashMap<>();
map.put("两年半","唱跳rap篮球");
正射,LinkedHashMap效果更好,然后你修改代码
Map<String, String> map = new LinkedHashMap<>();
map.put("两年半","唱跳rap篮球");
发现用LinkedHashMap会有隐患,还是得改回去用HashMap,根据传入的条件来决定用HashMap还是LinkedHashMap
public Map<String, String> getMap(String param) {
Map<String, String> map = null;
if (param.equals("HashMap")) {
map = new HashMap<>();
} else if (param.equals("LinkedHashMap")) {
map = new LinkedHashMap<>();
}
return map;
}
这里你得用TreeMap;你又要改代码,哦豁
\------------------------------------------------------正经的分割线
有没有一种办法可以让你不修改代码呢,这时候反射就派上用场了
概念:反射是Java的一种机制,让我们可以在运行时获取类的信息
作用:通过反射,我们可以在程序运行时动态创建对象,还能获取到类的所有信息,比如它的属性、构造器、方法、注解等;
直接举例
public Map<String, String> getMap(String className) {
Class clazz = Class.forName(className);
Constructor constructor = clazz.getConstructor();
return (Map<String, String>) constructor.newInstance();
}
这时候不管你需要什么Map,只要实现了Map接口,你都能通过getMap获得,只需要传入对应Map的全限定名,例如java.util.HashMap / java.util.LinkedHashMap
\------------------------------------------------------不正经的分割线
java中反射的用法非常非常多,常见的有以下这几个:
一、在运行时获取一个类的 Class 对象
二、在运行时构造一个类的实例化对象
三、在运行时获取一个类的所有信息:变量、方法、构造器、注解
一、获取class对象
三种方法
1、类名.class:这种获取方式只有在编译前已经声明了该类的类型才能获取到 Class 对象
Class<HashMap> hashMap= HashMap.class;
2、实例.getClass():通过实例化对象获取该实例的 Class 对象
Map<String, String> hashMap = new HashMap<>();
Class<? extends Map> hashMapClass = hashMap.getClass();
3、Class.forName(“类的全限定名”):通过类的全限定名获取该类的 Class 对象
Class<?> hashMap= Class.forName("java.util.HashMap");
拿到 Class对象就可以对它为所欲为了:调用它的方法、获取属性、获取类信息。
二、构造类的实例化对象
通过反射构造一个类的实例方式有2种:
1、Class 对象调用newInstance()方法
Class<?> hashMapClass = Class.forName("java.util.HashMap");
HashMap hashMapInstance = (HashMap) hashMapClass.newInstance();
注意:即使 HashMap已经显式定义了构造方法,通过 newInstance() 创建的实例中,所有属性值都是对应类型的初始值,因为 newInstance() 构造实例会调用默认无参构造器。
2、Constructor 构造器调用newInstance()方法
Class<?> hashMapClass = Class.forName("java.util.HashMap");
Constructor<?> constructor = hashMapClass.getConstructor();
constructor.setAccessible(true);
HashMap newInstance = (HashMap) constructor.newInstance();
通过 getConstructor(Object… paramTypes) 方法指定获取指定参数类型的 Constructor, Constructor 调用 newInstance(Object… paramValues) 时传入构造方法参数的值,同样可以构造一个实例,且内部属性已经被赋值。
通过Class对象调用 newInstance() 会走默认无参构造方法,如果想通过显式构造方法构造实例,需要提前从Class中调用getConstructor()方法获取对应的构造器,通过构造器去实例化对象。
三、获取类的所有信息
1、获取类中的变量(Field)
Field[] getFields():获取类中所有被public修饰的所有变量
Field getField(String name):根据变量名获取类中的一个变量,该变量必须被public修饰
Field[] getDeclaredFields():获取类中所有的变量,但无法获取继承下来的变量
Field getDeclaredField(String name):根据姓名获取类中的某个变量,无法获取继承下来的变量
2、获取类中的方法(Method)
Method[] getMethods():获取类中被public修饰的所有方法
Method getMethod(String name, Class… paramTypes):根据名字和参数类型获取对应方法,该方法必须被public修饰Method[] getDeclaredMethods():获取所有方法,但无法获取继承下来的方法
Method getDeclaredMethod(String name, Class…paramTypes):根据名字和参数类型获取对应方法,无法获取继承下来的方法
3、获取类的构造器(Constructor)
Constuctor[] getConstructors():获取类中所有被public修饰的构造器 Constructor
getConstructor(Class… paramTypes):根据参数类型获取类中某个构造器,该构造器必须被public修饰Constructor[] getDeclaredConstructors():获取类中所有构造器
Constructor getDeclaredConstructor(class… paramTypes):根据参数类型获取对应的构造器
反射的应用场景
标签:反射,java,HashMap,newInstance,构造,获取,Class,类中 From: https://blog.51cto.com/u_14299064/73976421、Spring 实例化对象:当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里面所有的标签实例化到IOC容器中。
2、反射 + 工厂模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,工厂类可以应对各种新增的类,反射可以使得程序更加健壮。
3、JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类