Program Tip

Java에서 유형을 메소드 매개 변수로 전달하는 방법

programtip 2020. 10. 29. 19:12
반응형

Java에서 유형을 메소드 매개 변수로 전달하는 방법


Java에서 유형을 매개 변수로 전달 (또는 변수로 선언)하려면 어떻게해야합니까?

유형 인스턴스 를 전달하지 않고 유형 자체 (예 : int, String 등) 를 전달하고 싶습니다 .

C #에서는 다음과 같이 할 수 있습니다.

private void foo(Type t)
{
    if (t == typeof(String)) { ... }
    else if (t == typeof(int)) { ... }
}

private void bar()
{
    foo(typeof(String));
}

유형 t 인스턴스전달하지 않고 Java에서 방법이 있습니까?
아니면 내 정수 상수 나 열거 형을 사용해야합니까?
아니면 더 좋은 방법이 있습니까?

편집 : 다음은 foo에 대한 요구 사항입니다.
유형 t를 기반으로 다른 짧은 xml 문자열을 생성합니다.
if / else의 코드는 매우 작고 (한두 줄) 개인 클래스 변수를 사용합니다.


통과 할 수 Class<T>있습니다.

private void foo(Class<?> cls) {
    if (cls == String.class) { ... }
    else if (cls == int.class) { ... }
}

private void bar() {
    foo(String.class);
}

업데이트 : OOP 방식은 기능 요구 사항에 따라 다릅니다. 가장 좋은 방법은 인터페이스를 정의 foo()하고 두 가지 구체적인 구현을 구현 foo()한 다음 foo()현재 사용중인 구현을 호출 하는 것입니다. 다른 방법은으로 Map<Class<?>, Action>호출 할 수 actions.get(cls)있습니다. 이것은 인터페이스 및 구체적인 구현과 쉽게 결합됩니다 actions.get(cls).foo().


비슷한 질문이 있었으므로 아래에서 완전한 실행 가능한 답변을 작성했습니다. 내가해야 할 일은 클래스 (C)를 관련없는 클래스의 객체 (O)에 전달하고 그 객체 (O)가 요청했을 때 클래스 (C)의 새 객체를 내게 다시 내보내도록하는 것입니다.

아래 예는 이것이 수행되는 방법을 보여줍니다. Projectile 클래스 (Pebble, Bullet 또는 NuclearMissle)의 하위 유형으로로드하는 MagicGun 클래스가 있습니다. 흥미로운 점은 Projectile의 하위 유형으로로드하지만 해당 유형의 실제 오브젝트가 아니라는 것입니다. MagicGun은 촬영할 때 실제 물체를 만듭니다.

출력

You've annoyed the target!
You've holed the target!
You've obliterated the target!
click
click

코드

import java.util.ArrayList;
import java.util.List;

public class PassAClass {
    public static void main(String[] args) {
        MagicGun gun = new MagicGun();
        gun.loadWith(Pebble.class);
        gun.loadWith(Bullet.class);
        gun.loadWith(NuclearMissle.class);
        //gun.loadWith(Object.class);   // Won't compile -- Object is not a Projectile
        for(int i=0; i<5; i++){
            try {
                String effect = gun.shoot().effectOnTarget();
                System.out.printf("You've %s the target!\n", effect);
            } catch (GunIsEmptyException e) {
                System.err.printf("click\n");
            }
        }
    }
}

class MagicGun {
    /**
     * projectiles holds a list of classes that extend Projectile. Because of erasure, it
     * can't hold be a List<? extends Projectile> so we need the SuppressWarning. However
     * the only way to add to it is the "loadWith" method which makes it typesafe. 
     */
    private @SuppressWarnings("rawtypes") List<Class> projectiles = new ArrayList<Class>();
    /**
     * Load the MagicGun with a new Projectile class.
     * @param projectileClass The class of the Projectile to create when it's time to shoot.
     */
    public void loadWith(Class<? extends Projectile> projectileClass){
        projectiles.add(projectileClass);
    }
    /**
     * Shoot the MagicGun with the next Projectile. Projectiles are shot First In First Out.
     * @return A newly created Projectile object.
     * @throws GunIsEmptyException
     */
    public Projectile shoot() throws GunIsEmptyException{
        if (projectiles.isEmpty())
            throw new GunIsEmptyException();
        Projectile projectile = null;
        // We know it must be a Projectile, so the SuppressWarnings is OK
        @SuppressWarnings("unchecked") Class<? extends Projectile> projectileClass = projectiles.get(0);
        projectiles.remove(0);
        try{
            // http://www.java2s.com/Code/Java/Language-Basics/ObjectReflectioncreatenewinstance.htm
            projectile = projectileClass.newInstance();
        } catch (InstantiationException e) {
            System.err.println(e);
        } catch (IllegalAccessException e) {
            System.err.println(e);
        }
        return projectile;
    }
}

abstract class Projectile {
    public abstract String effectOnTarget();
}

class Pebble extends Projectile {
    @Override public String effectOnTarget() {
        return "annoyed";
    }
}

class Bullet extends Projectile {
    @Override public String effectOnTarget() {
        return "holed";
    }
}

class NuclearMissle extends Projectile {
    @Override public String effectOnTarget() {
        return "obliterated";
    }
}

class GunIsEmptyException extends Exception {
    private static final long serialVersionUID = 4574971294051632635L;
}

당신은 통과해야 Class...

private void foo(Class<?> t){
    if(t == String.class){ ... }
    else if(t == int.class){ ... }
}

private void bar()
{
   foo(String.class);
}

오, 그러나 그것은 추악하고 객체 지향적이지 않은 코드입니다. "if / else"및 "typeof"를 보는 순간 다형성을 생각해야합니다. 이것은 잘못된 길입니다. 제네릭은 여기서 당신의 친구라고 생각합니다.

얼마나 많은 유형을 다룰 계획입니까?

최신 정보:

String과 int에 대해 이야기하고 있다면 여기에 할 수있는 한 가지 방법이 있습니다. XmlGenerator 인터페이스로 시작합니다 ( "foo"로 충분 함).

package generics;

public interface XmlGenerator<T>
{
   String getXml(T value);
}

그리고 구체적인 구현 XmlGeneratorImpl :

    package generics;

public class XmlGeneratorImpl<T> implements XmlGenerator<T>
{
    private Class<T> valueType;
    private static final int DEFAULT_CAPACITY = 1024;

    public static void main(String [] args)
    {
        Integer x = 42;
        String y = "foobar";

        XmlGenerator<Integer> intXmlGenerator = new XmlGeneratorImpl<Integer>(Integer.class);
        XmlGenerator<String> stringXmlGenerator = new XmlGeneratorImpl<String>(String.class);

        System.out.println("integer: " + intXmlGenerator.getXml(x));
        System.out.println("string : " + stringXmlGenerator.getXml(y));
    }

    public XmlGeneratorImpl(Class<T> clazz)
    {
        this.valueType = clazz;
    }

    public String getXml(T value)
    {
        StringBuilder builder = new StringBuilder(DEFAULT_CAPACITY);

        appendTag(builder);
        builder.append(value);
        appendTag(builder, false);

        return builder.toString();
    }

    private void appendTag(StringBuilder builder) { this.appendTag(builder, false); }

    private void appendTag(StringBuilder builder, boolean isClosing)
    {
        String valueTypeName = valueType.getName();
        builder.append("<").append(valueTypeName);
        if (isClosing)
        {
            builder.append("/");
        }
        builder.append(">");
    }
}

If I run this, I get the following result:

integer: <java.lang.Integer>42<java.lang.Integer>
string : <java.lang.String>foobar<java.lang.String>

I don't know if this is what you had in mind.


If you want to pass the type, than the equivalent in Java would be

java.lang.Class

If you want to use a weakly typed method, then you would simply use

java.lang.Object

and the corresponding operator

instanceof

e.g.

private void foo(Object o) {

  if(o instanceof String) {

  }

}//foo

However, in Java there are primitive types, which are not classes (i.e. int from your example), so you need to be careful.

The real question is what you actually want to achieve here, otherwise it is difficult to answer:

Or is there a better way?


You can pass an instance of java.lang.Class that represents the type, i.e.

private void foo(Class cls)

참고URL : https://stackoverflow.com/questions/2240646/how-to-pass-a-type-as-a-method-parameter-in-java

반응형