java高级-反射的三种实例化模式及与工厂,单例模式的的关系

一、概述

    所谓反射,就是根据实例化对象找到对象的根源。

范例:观察Class对象的使用

/*根据对象找到对象的根源**/
public class Demo {
    public static void main(String[] args) {
        Date date = new Date();
        System.out.println(date.getClass());
    }
}

运行结果

c34ffea3bad47503665027022bf3e364da0.jpg

二、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());
    }
}

运行结果:

4e63f7bcba6a340b64ff7ca7485bf24ab24.jpg

2.【JVM直接支持】利用“类.Class”的形式来实例化

class Person{}

public class MainDemo {
    public static void main(String[] args) {
        Class<?> cls = Person.class;
        System.out.println(cls.getName());
    }
}

运行结果:

7c297a565933b24e135278cb7272a77c814.jpg

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();
        }
    }
}

运行结果:

67f5eca4fe8d29395cc40e1660ae937ab8f.jpg

这种模式不需要导入包(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();
        }
    }
}

运行结果:

64c2152c043f79609cb7e30cf2583dc60d7.jpg

但是在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();
        }
    }
}

运行结果

64c2152c043f79609cb7e30cf2583dc60d7.jpg

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;
        }
    }
}

运行结果:

d2c272ee7a545924249db8a5f3ffa86bd19.jpg

以上静态工厂模式存在弊端,每当增加一个子类,工厂类中就必须修改实例方法。所以要解决此问题,最好不使用关键字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;
    }
}

运行结果

d2c272ee7a545924249db8a5f3ffa86bd19.jpg

但是以上程序任然没有达到最好的效果,如果用户想增加接口,则必须增加工厂类中的实例化方法,任然要求修改factory类,所以,只能用泛型的方式来解决此问题。

1165faaf838fe8010b6c955e12aa7d86329.jpg

范例:使用泛型来解决增加接口的问题

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;
    }
}

运行结果

bf23b8d667e20121735b1b61e9294ff0621.jpg

此时的工厂设计模式将不会受限于指定的接口。

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");
    }
}

 

注:初学者,写的不好请见谅,如有相关问题记得私信我

转载于:https://my.oschina.net/chenzhou/blog/2208498

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值