如何获取并将一个对象的类作为参数传递给一个带有泛型的类中使用?

huangapple go评论75阅读模式
英文:

How to get and use the Class of an object as parameter into a generified class?

问题

我在如何使用getClass()来获取泛型类中的T方面遇到了一些问题。我想要像下面这样做:

SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
Class a = currentTbModel.getModelClass();
NewFrame1<a> newWindow = new NewFrame1<a>();
newWindow.setVisible(true);

我在SimpleTableModel中有一个名为getModelClass的函数,如下所示:

public Class<?> getModelClass() {
    return (modelData.get(0)).getClass();
}

我认为我可以使用a来传递这个类。为了澄清,我的SimpleTableModel、NewFrame1以及调用这些函数的类都在同一个包中,而类a实际上会在另一个包中。因此,当我执行a.getName()时,它会返回otherPackage.myClass。我不确定这是否是问题所在。

我没有找到任何关于如何使用Class来传递类型参数的答案,希望提问这个问题不会将我链接到通用的getClass解释,而是得到一个答案。

英文:

I have a bit of an issue in how I can use getClass() to get my T for my generified class. I want to do the following as it were:

    SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
    Class a = currentTbModel.getModelClass();
    NewFrame1&lt;a&gt; newWindow = new NewFrame1&lt;a&gt;();
    newWindow.setVisible(true);

I have the getModelClass function inside of my SimpleTableModel as such:

public Class&lt;?&gt; getModelClass() {
    return (modelData.get(0)).getClass();
}

I thought that I could use a to put through the class. To clarify, my SimpleTableModel, NewFrame1, and the class where I am calling these functions from are all in the same package, whereas class a would actually be in another package. So it returns otherPackage.myClass when I do a.getName(). I am unsure if this is the issue.

I didn't find any answers which showed how to use Class to put through a type parameter, so I hope that asking this won't link me to generic getClass explanations instead of an answer.

答案1

得分: 1

你在代码中的操作是尝试使用一个名为 aClass 实例的引用作为类型参数。

但是类型参数必须是字面类型名称,例如 String,或者类型参数。

你只能在方法或类上声明类型参数。

所以你可以在你的方法上定义一个类型参数(例如 T),并在代码中使用它,如下所示:

<T> void myMethod() {
    //...
    SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
    Class<T> a = (Class<T>) currentTbModel.getModelClass();
    NewFrame1<T> newWindow = new NewFrame1<T>();
    newWindow.setVisible(true);
}

注意,T 不添加任何信息,它只是一个句柄,因此你可以用通配符替换它:

void myMethod() {
    //...
    SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
    Class<?> a = (Class<T>) currentTbModel.getModelClass();
    NewFrame1<?> newWindow = new NewFrame1<?>();
    newWindow.setVisible(true);
}

由于类型参数存在于编译时,而类实例存在于运行时,所以它们无法影响类型参数,所以你不能真正改进这一点。

这也意味着 NewFrame 的类型参数不能在构造函数内部使用。

如果你想要这样做,你必须将类实例作为参数传递给构造函数:

void myMethod() {
    //...
    SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
    Class<?> a = (Class<T>) currentTbModel.getModelClass();
    NewFrame1<?> newWindow = new NewFrame1<>(a);
    newWindow.setVisible(true);
}

当然,它必须在构造函数中声明,并且你可以像上面描述的那样使用通配符或命名类型参数。

以下是我用于创建这个答案的完整示例:

public class Demo {

    public static void main(String[] args) {
        new Demo().run();
    }

    private void run() {
        Class<?> aClassInstance = getSomeClass();
        
        TypedClass<?> typedInstance = new TypedClass<>(aClassInstance);
    }

    private <T> void run2() {
        Class<T> aClassInstance = (Class<T>) getSomeClass();
        
        TypedClass<T> typedInstance = new TypedClass<>(aClassInstance);
    }

    private Class<?> getSomeClass() {
        return String.class;
    }

    static class TypedClass<T> {

        TypedClass(Class<T> typeClass) {
            
        }
    }
}
英文:

What you are doing in your code is to try to use a reference to a Class instance, named a for a type argument.

But type arguments have to be either literal type names, e.g. String or type parameters.

You can declare type parameters only on methods or on classes.

So you could define a type parameter on your method (e.g. T) and use it in your code as follows:

&lt;T&gt; void myMethod() {
    //...
    SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
    Class&lt;T&gt; a =(Class&lt;T&gt;) currentTbModel.getModelClass();
    NewFrame1&lt;T&gt; newWindow = new NewFrame1&lt;T&gt;();
    newWindow.setVisible(true);
}

Note that T doesn't add any information, it is just a handle, so you might replace it with a wildcard:

void myMethod() {
    //...
    SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
    Class&lt;?&gt; a =(Class&lt;T&gt;) currentTbModel.getModelClass();
    NewFrame1&lt;?&gt; newWindow = new NewFrame1&lt;?&gt;();
    newWindow.setVisible(true);
}

You can't really improve on this since type parameters live at compile time, while class instances exist and run time, so they can't affect type parameters.
This also means the type parameter to NewFrame can't be used inside the constructor.
If you want to do that you have to pass the class instance as an argument to the constructor:

void myMethod() {
    //...
    SimpleTableModel currentTbModel = (SimpleTableModel)jTable.getModel();
    Class&lt;?&gt; a =(Class&lt;T&gt;) currentTbModel.getModelClass();
    NewFrame1&lt;?&gt; newWindow = new NewFrame1&lt;?&gt;(a);
    newWindow.setVisible(true);
}

Of course it has to be declared in the constructor and again you might use wildcards or named type parameters as described above.

Full example, I used for creating this answer:


public class Demo {

	public static void main(String[] args) {
		new Demo().run();
	}

	private void run() {
		Class&lt;?&gt; aClassInstance = getSomeClass();
		
		TypedClass&lt;?&gt; typedInstance = new TypedClass&lt;&gt;(aClassInstance);
	}

	private &lt;T&gt; void run2() {
		Class&lt;T&gt; aClassInstance = (Class&lt;T&gt;) getSomeClass();
		
		TypedClass&lt;T&gt; typedInstance = new TypedClass&lt;&gt;(aClassInstance);
	}

	private Class&lt;?&gt; getSomeClass() {
		return String.class;
	}

	static class TypedClass&lt;T&gt; {

		TypedClass(Class&lt;T&gt; typeClass) {
			
		}
	}
	
}

huangapple
  • 本文由 发表于 2020年4月9日 07:46:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/61111787.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定