反射オブジェクトインスタンス
分析の一連の後、クラスのクラスのオブジェクトをインスタンス化するために取得することができますが、それでもオブジェクトのその意味は大きくないますが、次のような場合で反射されたコアの意味を理解することが可能であることが判明
-オブジェクトのインスタンスを反映します。Getクラス・オブジェクト・インスタンスの後に、そのオブジェクトの操作の形で、より重要なことには、JDK1.9の前の例のオブジェクトのインスタンス化の方法を反映クラスのクラスが提供されるだけでなく、最大の意義:公共TのnewInstance()スローないInstantiationException、IllegalAccessExceptionが、代わりに新たなキーワードを使用する方法の、しかし変更JDK1.9後:Class.getDeclaredConstructor()のnewInstance();.
-例:のnewInstanceの方法の一例()オブジェクト
1つの パッケージ反射.entityを反映認識;
2
3。 / **
4。 * @author :SKY
。5 * @version :0.0.1
。6 * /
7 パブリック クラス人{
8。 公的人(){ // 限り例としていずれの場合オブジェクトは、クラスのコンストラクタを呼び出す必要があります
9。 のSystem.out.println( "Personオブジェクトがインスタンス化される" );
10 }
11
12である @Override
13である パブリック文字列のtoString(){
14 リターンは "私が良い午前" 、
15 }
16 }
1 パブリック クラスデモ{
2 公共 静的 ボイドメイン(文字列[]引数)がスローないInstantiationExceptionが{で、ClassNotFoundExceptionが、IllegalAccessExceptionがを
3 =クラスAClassはClass.forNameの<?>( "理解反射反射.entity.Person。" )
。4 オブジェクトO aClass.newInstance =(); // オブジェクトをインスタンス化する
。5 のSystem.out.println(O);
6 }
。7 }
- オペレーティング結果
Personオブジェクトをインスタンス化され
、私は良い人だ
終了コードで仕上げプロセス 0
- 今はまだ新しいキーワードの使用と本質的に同等であるパラメータクラスのコンストラクタ、なしで呼ばれるように、実装プロセスのオブジェクトのインスタンスによって反射されるが、この方法は、JDK1.9後に交換されたデフォルトのクラス理由newInstanceクラス()メソッドは、引数なしで唯一のコンストラクタを呼び出すことができ、多くの開発者ので、その説明は正確ではないこと、それが変換された形態(フォローアップについて説明します)
第二の反射や工場のデザインパターンの
終わりでインスタンスの反射が提供される理由:それは新しいキーワードを使用することに加えて対象となる場合はインスタンス化プロセスでは、あなたも質問を熟考し、その後完了するためにリフレクションを生き延びことができますか? ?キーワードは、新規またはそれの反射を利用して、オブジェクトのインスタンス化で使用する
クライアントプログラム:あなたはより良い、このような問題を解決したい場合は、最善の解決策は、工場出荷時のデザインパターンの最も重要な機能を解決するために、工場の設計パターンを介して説明することです- 。クラスは、直接インスタンス化マネージャオブジェクト、ファクトリインタフェース、従来の工場の設計パターンを介して取得されたオブジェクトをインスタンス化の発生と関連する唯一のインターフェースを必要としません。
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 }