java reflection (two) - reflecting Applications

A reflective object instance

  After a series of analysis found that although you can get to instantiate an object of class Class, but still get that sense of the object is not large, it is possible to understand the core meaning reflected by the following cases
- reflected instance of the object: Get after class object instance that the greatest significance not only in the form of operation of an object, more importantly, there is provided a class class reflecting object instantiation method in the previous example of JDK1.9: public T newInstance () throw InstantiationException, IllegalAccessException, instead of the method using the new keyword, but after the change JDK1.9: Class.getDeclaredConstructor () newInstance ();.
- example: example of the method to newInstance () object

. 1  Package . Recognized reflecting reflection .entity;
 2  
. 3  / ** 
. 4  * @author : SKY
 . 5  * @version : 0.0.1
 . 6   * / 
. 7  public  class the Person {
 . 8      public the Person () {    // any case as long as the Examples the object must call the class constructor 
. 9          System.out.println ( "the Person object is instantiated" );
 10      }
 . 11  
12 is      @Override
 13 is      public String toString () {
 14          return "I am a good" ;
 15      }
 16 }
. 1  public  class Demo {
 2      public  static  void main (String [] args) throws a ClassNotFoundException, IllegalAccessException, an InstantiationException is {
 . 3          <?> = Class aClass the Class.forName ( "Understanding reflection reflection .entity.Person." );
 . 4          Object O aClass.newInstance = ();     // instantiate the object 
. 5          System.out.println (O);
 . 6      }
 . 7 }

--operation result

Person object is instantiated 
I am a good person 

Process Finished with Exit code 0

- is now reflected by the object instance of the implementation process, still to be called without parameter class constructor, which is essentially equivalent to the use of the new keyword, but the method was replaced after JDK1.9, because the default Class newInstance class () method can be called only constructor with no arguments, many developers so that its description is not accurate, then it will be converted form (follow-up will be described)

Second reflection and factory design pattern
  instantiation process if it is to be an object In addition to using the new keyword, you can also survived reflection to complete then pondering a question: Why there is provided a reflection of instantiated in the end? use the keyword is new or instantiation of objects using reflection of it?
- If you want to better solve such problems, the best solution is to explain through the factory design pattern to solve the most important feature of the factory design pattern: the client program. class does not directly involve the instantiation manager object, only the interface associated with the occurrence of instantiating objects acquired through the factory interface, a conventional factory design pattern:

 1 interface Message{
 2     public void send();     //消息发送
 3 }
 4 class NetMessage implements Message{        //网络消息实现类
 5     @Override
 6     public void send() {
 7         System.out.println("发送网络消息");
 8     }
 9 }
10 public class FactoryDemo {
11     public static void main(String[] args) {
12         Message message = new NetMessage(); //如果直接实例化则一定会有耦合问题
13     }
14 }

 

 

--在实际的开发中,接口的主要作用是为不同的层提供有一个操作的标准.但是此时如果直接将一个子类设置为接口实例化操作,那么一定会有耦合问题,所以使用了工厂设计模式来解决此问题.
--范例:传统的工厂设计模式

 1 interface Message {
 2     public void send();     //消息发送
 3 }
 4 
 5 class NetMessage implements Message {        //网络消息实现类
 6     @Override
 7     public void send() {
 8         System.out.println("发送网络消息");
 9     }
10 }
11 
12 class Factory {
13     private Factory() {
14     }     //没有产生实例化对象的意义
15 
16     public static Message getInstance(String className) {
17         if ("NetMessage".equals(className)) {
18             return new NetMessage();
19         }
20         return null;
21     }
22 }
23 
24 public class FactoryDemo {
25     public static void main(String[] args) {
26         Message message = Factory.getInstance("NetMessage");
27         message.send();
28     }
29 }

--此种工厂设计模式属于静态工厂设计模式,此时如果追加一个子类,那么工厂类就需要进行相应的修改(追加相应的判断语句),否则无法获得新的子类的实例化对象.工厂设模式最有效解决的是子类与客户端的耦合问题,但是解决的核心思想是在于提供有一个工厂类作为过渡端,可是随着项目的进行,Message接口可能会有更多的子类,而且随着时间的推移,子类会越来越多,因此工厂类永远都需要修改,并且永无停止之日.
--此时最好的解决方案就是不使用关键字new来完成对象的实例化,因为关键字new在使用的时候需要有一个明确的类存在.而newInstance()的方法只需要有一个明确表示类名称的字符串即可应用:

 1 interface Message {
 2     public void send();     //消息发送
 3 }
 4 
 5 class NetMessage implements Message {        //网络消息实现类
 6     @Override
 7     public void send() {
 8         System.out.println("发送网络消息");
 9     }
10 }
11 
12 class Factory {
13     private Factory() {
14     }     //没有产生实例化对象的意义
15 
16     public static Message getInstance(String className) throws Exception {
17         return (Message) Class.forName(className).newInstance();
18     }
19 }
20 
21 public class FactoryDemo {
22     public static void main(String[] args) throws Exception {
23         Message message = Factory.getInstance("反射.反射应用案例.NetMessage");
24         message.send();
25     }
26 }

--此时如果对子类继续进行扩充的话,是没有必要修改工厂类的.利用反射机制实现的工厂设计模式,最大的优势在于,对于接口的子类的扩充,将不再影响到工厂类的定义.但是现在依然需要进行思考,在实际的项目开发之中,有可能会存在大量的接口,并且这些接口可能都需要通过工厂类来实例化对象,所以此时的工厂设计模式不应该只为一个Message接口服务,而应该变为为所有的接口服务(使用泛型实现开发需求): 

 1 interface Service {
 2     public void service();
 3 }
 4 
 5 class HouseService implements Service {
 6     @Override
 7     public void service() {
 8         System.out.println("为您的住房提供服务.");
 9     }
10 }
11 
12 interface Message {
13     public void send();     //消息发送
14 }
15 
16 class NetMessage implements Message {        //网络消息实现类
17     @Override
18     public void send() {
19         System.out.println("发送网络消息");
20     }
21 }
22 
23 class Factory {
24     private Factory() {
25     }     //没有产生实例化对象的意义
26 
27     /**
28      * 获取接口实例化对象
29      *
30      * @param className 接口的子类
31      * @param tClass    描述的是一个接口的类型
32      * @return 如果子类存在则返回指定接口
33      * @throws Exception
34      */
35     public static <T> T getInstance(String className, Class<T> tClass) throws Exception {
36         return tClass.cast(Class.forName(className).newInstance());
37     }
38 }
39 
40 public class FactoryDemo {
41     public static void main(String[] args) throws Exception {
42         Message message = Factory.getInstance("反射.反射应用案例.NetMessage",Message.class);
43         message.send();
44         Service instance = Factory.getInstance("反射.反射应用案例.HouseService", Service.class);
45         instance.service();
46     }
47 }

--此时的工厂设计模式才是所谓的高可用的工厂设计模式,而这种操作的实现依赖的就是泛型.此时的工厂设计模式将不再受限于指定的接口,可以为所有的接口提供实例化对象.

三.反射与单例设计模式
  单例设计模式的核心本质在于类内部的构造方法私有化,在类的内部产生实例化对象之后在外部通过static方法获取到实例化对象进行类中的结构调用.单例设计模式一共有两种,懒汉式和饿汉式(饿汉式的单例是不再本次的讨论范围之内的,主要讨论懒汉式的单例)
--范例:观察懒汉式单例的问题

 1 class Singleton {
 2     private static Singleton instance = null;
 3 
 4     private Singleton() {
 5     }
 6 
 7     public static Singleton getInstance() {
 8         if (instance == null) {
 9             instance = new Singleton();
10         }
11         return instance;
12     }
13 
14     public void print() {
15         System.out.println("单例模式加载");
16     }
17 
18 }
19 
20 public class LazyLoadDemo {
21     public static void main(String[] args) {
22         Singleton singleton = Singleton.getInstance();
23         singleton.print();
24     }
25 }

--此时我们的操作是在单线程的环境下运行的,如果使用多线程

 1 class Singleton {
 2     private static Singleton instance = null;
 3 
 4     private Singleton() {
 5         System.out.println(Thread.currentThread().getName() + " 实例化单例对象");
 6     }
 7 
 8     public static Singleton getInstance() {
 9         if (instance == null) {
10             instance = new Singleton();
11         }
12         return instance;
13     }
14 
15     public void print() {
16         System.out.println("单例模式加载");
17     }
18 
19 }
20 
21 public class LazyLoadDemo {
22     public static void main(String[] args) {
23         for (int i = 0; i < 3; i++) {
24             new Thread(() -> {
25                 Singleton.getInstance();
26             }, "[单例创建者" + (i + 1) + "]").start();
27         }
28     }
29 }

--运行结果

[单例创建者1] 实例化单例对象
[单例创建者2] 实例化单例对象
[单例创建者3] 实例化单例对象

Process finished with exit code 0

--单例设计模式最大的特点是在整体运行之中,只允许产生一个实例化对象,当有了若干实例化对象之后,那么就不是单例设计模式了,我们可以大致分析单例模式的运行流程如下:
  1.判断instance是否为空?
  2.如果instance为空,实例化instance对象
  3.返回当前的instance
--因此在多线程的设计中,每一个线程在执行步骤1的时候都会认为此时的对象为空,那么都会去创建这个对象的实例,这样一来单例设计模式也就失去了意义,如果想要解决这类问题,关键的核心就在于要解决同步处理,而解决同步处理的核心就是使用synchronized关键字

 1 class Singleton {
 2     private static Singleton instance = null;
 3 
 4     private Singleton() {
 5         System.out.println(Thread.currentThread().getName() + " 实例化单例对象");
 6     }
 7 
 8     public static synchronized Singleton getInstance() {
 9         if (instance == null) {
10             instance = new Singleton();
11         }
12         return instance;
13     }
14 
15     public void print() {
16         System.out.println("单例模式加载");
17     }
18 
19 }
20 
21 public class LazyLoadDemo {
22     public static void main(String[] args) {
23         for (int i = 0; i < 3; i++) {
24             new Thread(() -> {
25                 Singleton.getInstance();
26             }, "[单例创建者" + (i + 1) + "]").start();
27         }
28     }
29 }

--运行结果

[单例创建者1] 实例化单例对象

Process finished with exit code 0

--此时却是进行了同步处理,但是这个同步的代价却是很大的,因为效率会降低.因为整体代码中实际上只有一块区域需要同步处理,那就是instance对象的实例化处理部分,在这样的情况下同步加的未免显得有些草率,更加合理的进行同步处理:

 1 class Singleton {
 2     //在对象实例化的时候,应该立刻与主内存中的实例对象保持同步,而不应该存在副本
 3     private static volatile Singleton instance = null;  
 4 
 5     private Singleton() {
 6         System.out.println(Thread.currentThread().getName() + " 实例化单例对象");
 7     }
 8 
 9     public static Singleton getInstance() {
10         synchronized (Singleton.class) { //static方法只能使用Singleton.class
11             if (instance == null) {
12                 instance = new Singleton();
13             }
14         }
15         return instance;
16     }
17 
18     public void print() {
19         System.out.println("单例模式加载");
20     }
21 
22 }
23 
24 public class LazyLoadDemo {
25     public static void main(String[] args) {
26         for (int i = 0; i < 3; i++) {
27             new Thread(() -> {
28                 Singleton.getInstance();
29             }, "[单例创建者" + (i + 1) + "]").start();
30         }
31     }
32 }

Guess you like

Origin www.cnblogs.com/skykuqi/p/11421787.html