読者です 読者をやめる 読者になる 読者になる

KZKY memo

自分用メモ.

Java Reflection: Call by Name Singleton Class

Call by nameでクラスを呼ぶのは,Javaでは簡単

Class<? extend Parent> clazz = Class.forName(className);
clazz.newInstance()

しかし,classNameがシングルトンだったらどうなるかというと,
普通シングルトンのコンストラクタはprivateなのでException発生.

ではどうするかというと,DeclaredConstructorを持ってきて,
setAccessible(true)にする.

しかし,この方法はSecuritManagerに制限がかかっていると使えない.
そこで,MethodInvocationする.

それぞれの例下記に示す.

クラス一覧

Singleton
SampleApp
  • CreateObjectByNewInstanceMethodSample.java
  • CreateSingletonByDeclaredConstructorSample.java
    • privateの制約を解く
  • CreateSingletonByMethodReflectionSample.java
    • static methodでシングルトン作成

Model.java

package edu.kzk.java_samle.reflection;

public interface Model {
    public void execute();
}

ModelBase.java

package edu.kzk.java_samle.reflection;

public class ModelBase implements Model {
    protected static ModelBase instance; 
    protected ModelBase(){};
    
    public void execute() {System.out.println("Execute!");};
}

ModelImpl.java

package edu.kzk.java_samle.reflection;

public class ModelImpl extends ModelBase {
    protected ModelImpl(){};
    
    public static ModelBase getInstance() {
        if (instance == null) {
            instance = new ModelImpl(); 
        }
        
        return instance;
    }
    
    @Override
    public void execute() {
        super.execute();
    }
    
}

CreateObjectByNewInstanceMethodSample.java

package edu.kzk.java_samle.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class CreateObjectByNewInstanceMethodSample {

    public static void main(String[] args) {
        // class
        String className = "edu.kzk.java_samle.reflection.ModelImpl";

        try {
            Class<? extends ModelBase> clazz = 
                    (Class<? extends ModelBase>) Class.forName(className);

            // new 
            ModelBase model = (ModelBase) clazz.newInstance();

            model.execute();

        } catch (ClassNotFoundException | SecurityException | IllegalAccessException | IllegalArgumentException | InstantiationException e) {

            e.printStackTrace();
        }

    }

}

CreateSingletonByDeclaredConstructorSample.java

package edu.kzk.java_samle.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class CreateSingletonByDeclaredConstructorSample {

    public static void main(String[] args) {
        // class
        String className = "edu.kzk.java_samle.reflection.ModelImpl";

        try {
            Class<? extends ModelBase> clazz = 
                    (Class<? extends ModelBase>) Class.forName(className);

            // constructor
            Constructor constructor = clazz.getDeclaredConstructor();
            constructor.setAccessible(true);
            ModelBase model = (ModelBase) constructor.newInstance();
            
            model.execute();

        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) {

            e.printStackTrace();
        }

    }

}

CreateSingletonByMethodReflectionSample.java

package edu.kzk.java_samle.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class CreateSingletonByMethodReflectionSample {

    public static void main(String[] args) {
        
        // class
        String modelName = "edu.kzk.java_samle.reflection.ModelImpl";

        try {
            Class<? extends ModelBase> clazz = 
                    (Class<? extends ModelBase>) Class.forName(modelName);
            
            // show methods
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                System.out.println(method.toString());
            }
            
            System.out.println("");
            
            // invoke method
            Method method = clazz.getMethod("getInstance");
            ModelBase model = (ModelBase) method.invoke(null);
            
            model.execute();
            
        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            
            e.printStackTrace();
        }
        
        
    }

}