一、概述
所谓反射,就是根据实例化对象找到对象的根源。
范例:观察Class对象的使用
/*根据对象找到对象的根源**/ public class Demo { public static void main(String[] args) { Date date = new Date(); System.out.println(date.getClass()); } }
运行结果:
二、Class类对象三种实例化模式
反射之中所有的核心操作都是通过Class类对象展开的,可以说Class是反射操作的根源所在,要想获取他的实例化对象,可以采用三种方式来完成。
1.【Object类支持】Object类可以通过实例化对象获取Class
class Person{} public class MainDemo { public static void main(String[] args) { Person person = new Person(); Class<? extends Person> cls = person.getClass(); System.out.println(cls.getName()); } }
运行结果:
2.【JVM直接支持】利用“类.Class”的形式来实例化
class Person{} public class MainDemo { public static void main(String[] args) { Class<?> cls = Person.class; System.out.println(cls.getName()); } }
运行结果:
3.【Class类支持】在Class类中提供了一个static方法
- 方法:public static Class<?> forName(String className) throws ClassNotFoundException;
package com.cz.test; public class Person { }
public class MainDemo { public static void main(String[] args) { try { Class<?> cls = Class.forName("com.cz.test.Person"); System.out.println(cls.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
运行结果:
这种模式不需要导入包(import语句),直接通过字符串的类名来操作,如果该类不存在,则会抛出“ClassNotFoundException”异常。
三、相关经典案例
1.反射实例化对象
范例:通过newInstance()来实例化对象
package com.cz.test; public class Person { public Person(){ System.out.println("这是无参构造方法!!"); } public String toString(){ return "一个努力的人!!"; } }
public class MainDemo { public static void main(String[] args) { try { Class<?> cls = Class.forName("com.cz.test.Person"); try { Object obj = cls.newInstance(); System.out.println(obj); } catch (Exception e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
运行结果:
但是在JDK1.9之后就被不推荐使用了,主要是因为默认的Class类中的newInstance()方法只能够调用无参构造方法,所以很多开发者认为其描述不准确,所以将它变换了形式。
范例:通过getDeclaredConstructor().newInstance()来实现
public class MainDemo { public static void main(String[] args) { try { Class<?> cls = Class.forName("com.cz.test.Person"); try { Object obj = cls.getDeclaredConstructor().newInstance(); System.out.println(obj); } catch (Exception e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
运行结果:
2.反射与工厂设计模式
工厂设计模式不直接牵扯到对象的实例化管理,只与接口发生关联,通过工厂类获取指定接口的实例化。
范例:传统工厂设计模式
public class Test { public static void main(String[] args) { IMessage iMessage = Factory.getInstance("NetMessage"); iMessage.send(); } } interface IMessage{ void send(); } class NetMessage implements IMessage{ @Override public void send() { System.out.println("网络消息发送"); } } class Factory{ private Factory(){ //无参构造器,私有化 } public static IMessage getInstance(String classname){ //实例化方法 if("NetMessage".equals(classname)){ return new NetMessage(); }else{ return null; } } }
运行结果:
以上静态工厂模式存在弊端,每当增加一个子类,工厂类中就必须修改实例方法。所以要解决此问题,最好不使用关键字new.利用反射机制来实现。
范例:解决添加子类后必须修改工厂类的弊端
public class Test { public static void main(String[] args) { IMessage iMessage = Factory.getInstance("NetMessage"); iMessage.send(); } } interface IMessage{ void send(); } class NetMessage implements IMessage{ @Override public void send() { System.out.println("网络消息发送"); } } class Factory{ private Factory(){ } public static IMessage getInstance(String classname){ IMessage iMessage = null; try { iMessage = (IMessage)Class.forName(classname).getDeclaredConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); } return iMessage; } }
运行结果:
但是以上程序任然没有达到最好的效果,如果用户想增加接口,则必须增加工厂类中的实例化方法,任然要求修改factory类,所以,只能用泛型的方式来解决此问题。
范例:使用泛型来解决增加接口的问题
public class Test { public static void main(String[] args) { IMessage iMessage = Factory.getInstance("NetMessage",NetMessage.class); iMessage.send(); IService iService = Factory.getInstance("HouseService",HouseService.class); iService.service(); } } interface IMessage{ void send(); } class NetMessage implements IMessage{ @Override public void send() { System.out.println("网络消息发送"); } } interface IService{ void service(); } class HouseService implements IService{ @Override public void service() { System.out.println("提供住房服务"); } } class Factory{ private Factory(){ } public static <T> T getInstance(String classname,Class<T> clazz){ T intance = null; try { intance = (T)Class.forName(classname).getDeclaredConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); } return intance; } }
运行结果:
此时的工厂设计模式将不会受限于指定的接口。
3.反射与单例设计模式
/** * 单例模式(懒汉式) */ public class Demo1 { public static void main(String[] args) { for(int i = 0; i < 3 ; i++){ new Thread(()->{ Singleton.getSingleton().print(); },"线程"+i).start(); } } } class Singleton{ public static volatile Singleton singleton = null; private Singleton(){ //私有化构造方法 System.out.println(Thread.currentThread().getName()+"实例化"); } public static Singleton getSingleton(){ if(singleton == null){ synchronized(Singleton.class){ if(singleton == null) { singleton = new Singleton(); } } } return singleton; } public void print(){ System.out.println("666"); } }
注:初学者,写的不好请见谅,如有相关问题记得私信我