Java学习路线-29:反射机制与应用案例

第21 章 : 认识反射机制

99 反射机制简介

Java的精髓所在
动态获取信息以及动态调用对象方法的功能

所有技术实现的目标只有一点:重用性

正:类 -> 实例对象
反:实例对象 -> 类

找到对象的根源

Object.getClass() 

100 Class类对象的三种实例化模式

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement

要实例化的类

class Person{}

1、Object类支持
Object类可以根据实例化对象获取Class对象

缺点:
如果想获得类对象,则必须产生指定类对象后才能获得

Person person = new Person();
Class cls = person.getClass();

System.out.println(cls.getName());
// Person

2、JVM直接支持
采用类.class 直接实例化
如果要采用这种模式,则必须导入程序所对应开发包

Class cls = Person.class;

System.out.println(cls.getName());
// Person

3、Class类支持
Class类中提供了static方法

public static Class<?> forName(String className)

特点:
直接使用字符串形式定义要使用的类型,
程序不需要编写import,不存在则抛出异常

Class cls = Class.forName("Person");

System.out.println(cls.getName());
// Person

第22 章 : 反射应用案例

101 反射实例化对象

获取Class对象意义:
Class对象提供有一个对象的反射实例化方法

1、JDK<1.9

public T newInstance()
// 等价于关键字new, 只能调用无参构造 JDK>=1.9之后弃用

示例

Class cls = Class.forName("Person");
System.out.println(cls.newInstance());
// Person@2503dbd3

2、JDK>=1.9

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

示例

Class cls = Class.forName("Person");
System.out.println(cls.getDeclaredConstructor().newInstance());
// Person@2503dbd3

任何情况下如果要实例化对象则一定要调用类中的构造方法

102 反射与工厂设计模式

工厂设计模式:
通过工厂类获取指定接口实例化对象

接口的主要作用是为不同的层提供有一个操作的标准
如果直接将一个子类设置为接口实例化操作,那么一定会有耦合
工厂设计模式解决子类与客户端的耦合问题

1、静态工厂设计模式
如果子类增加,工厂类一定要做出修改
解决一个子类实例化

IMessage
    -NetMessage
    -CloudMessage

Factory // 通过传入的参数获取子类

Client 
interface IMessage {
    public void send(String message);
}

class Message implements IMessage {

    @Override
    public void send(String message) {
        System.out.println("发送: " + message);
    }
}

class Factory {
    private Factory() {
    }

    public static IMessage getInstance(String className) {
        if ("Message".equalsIgnoreCase(className)) {
            return new Message();
        }

        return null;
    }
}

public class Demo {
    public static void main(String[] args) {
        IMessage message = Factory.getInstance("message");
        message.send("nihao");
    }
}

2、利用反射实现工厂设计模式
解决一个接口多个子类实例化

修改工厂类代码

class Factory {
    private Factory() {
    }

    public static IMessage getInstance(String className) {
        IMessage message = null;

        try {
            message = (IMessage)Class.forName(className).getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return message;
    }
}

3、泛型反射实现工厂设计模式
解决所有接口子类实例化


class Factory {
    private Factory() {
    }

    public static <T> T getInstance(String className, Class<T> clazz) {
        T instance = null;

        try {
            instance = (T)Class.forName(className).getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return instance;
    }
}

public class Demo {
    public static void main(String[] args) {
        IMessage message = Factory.getInstance("Message", IMessage.class);
        message.send("nihao");
    }
}

103 反射与单例设计模式

单例设计模式:
类的构造函数私有化,通过static方法获取实例化对象
-懒汉式
-饿汉式

class Singleton{
    private static Singleton instance = null;

    private Singleton() {
    }

    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }

    public void print(){
        System.out.println("Singleton");
    }
}

class Demo{
    public static void main(String[] args) {
        Singleton instance = Singleton.getInstance();
        instance.print();
    }
}

多线程下执行,产生多个实例化对象

class Singleton{
    private static Singleton instance = null;

    private Singleton() {
        System.out.println("Singleton " + Thread.currentThread().getName());
    }

    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
    public void print(){
        System.out.println("Singleton print");
    }
}

class Demo{
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                Singleton instance = Singleton.getInstance();
                instance.print();
            }, "instance" + i).start();
        }

        /**
         * 输出结果
         * Singleton instance0
         * Singleton instance1
         * Singleton print
         * Singleton instance2
         * Singleton print
         * Singleton print
         */
    }
}

修改为同步处理

class Singleton{
    // volatile 不使用副本
    private static volatile Singleton instance = null;

    private Singleton() {
        System.out.println("Singleton " + Thread.currentThread().getName());
    }

    // synchronized不在函数上加,而是在内部代码块加,提高执行效率
    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                if(instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    
    public void print(){
        System.out.println("Singleton print");
    }
}

class Demo{
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(()->{
                Singleton instance = Singleton.getInstance();
                instance.print();
            }, "instance" + i).start();
        }

        /**
         * 输出结果
         * Singleton instance1
         * Singleton print
         * Singleton print
         * Singleton print
         */
    }
}

面试题:单例设计模式
1、实现饿汉式单例设计模式,构造函数私有化
2、Java中用到单例设计模式的类:
Runtime, Pattern, Spring框架
3、懒汉式单例设计模式的问题

发布了1392 篇原创文章 · 获赞 347 · 访问量 123万+

猜你喜欢

转载自blog.csdn.net/mouday/article/details/103789045