返回信息流已经决定改成这样了
```java
class Foo<T>{
private final Class<T> mClazz;
public Foo(Class<T> clz){
mClass = clz;//需要的时候直接拿就好
}
public void doSth(){
T t;
//这里我需要拿到t的class该怎么做呢-> mClazz
}
}
```
--------------------------------------------------------------
```java
class Foo<T>{
public void doSth(){
T t;
//这里我需要拿到t的class该怎么做呢?
}
}
```
参考了http://stackoverflow.com/questions/3437897/how-to-get-a-class-instance-of-generics-type-t这个
的确可以在构造的时候把类型传进来,但是我觉得 Foo<Bar> foo = new Foo<Bar>(Bar.class); 这样写很蠢。。。
还有用这种方法能拿到的:
entityBeanType = ((Class) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]);
不过这种办法似乎不科学(至于为什么我还是没搞明白)
https://www.oschina.net/code/snippet_155593_50917
为什么会这样呢?明明是有了范型,为什么连一个运行时class都拿得不熟练啊。
有没有人遇到类似问题的,求助一下。嗯嗯。
这是一条镜像帖。来源:北邮人论坛 / java / #54396同步于 2016/12/22
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
[已解决]关于运行时获取范型的class
ytinrete
2016/12/22镜像同步8 回复
订阅后,新回复会通过你的通知中心匿名送达。
8 条回复
```java
public class SimpleTest {
public static class Tee<T>{
public void doths(T a){
System.out.println(a.getClass());
}
}
@Test
public void test(){
Tee<Number> a = new Tee<Number>();
a.doths(1);
Tee<String> b = new Tee<>();
System.out.println(new TypeToken<Tee<String>>() {}.getType());
}
}
```
你这个路子也太野了吧。。
T t;没有办法实例化的,怎么拿类型?
【 在 ytinrete 的大作中提到: 】
: [md]
:
: ```java
: ...................
10年前,Java开发人员设计Java1.5,加入泛型时候,面对了两种选择:
1. 重新设计JVM,将泛型作为JVM的特性,但会牺牲向前兼容性。
2. 将Java的泛型作为Java语言级的特性,但翻译到JVM bytecode时把泛型参数都擦除(type erasure),这样JVM不会知道泛型的存在,但可以保持兼容Java1.4的bytecode。
在两种选择之间,它们选择了2。于是,Java语言级的“泛型”参数,到了JVM里就都擦掉了,所以Foo<T>和Foo<Object>在编译成JVM bytecode时都是一样的,那个参数在运行时也就拿不到了。
默哀。
【 在 ytinrete 的大作中提到: 】
: [md]
:
: ```java
: ...................
附件(4.7MB)
顺便来炫耀一下Scala。Scala有一种特殊语法:
class Foo[T: ClassTag]
其中方括号部分是泛型参数。但是,这里,T: ClassTag的意思是,要想生成一个Foo[T]实例,当前作用域里必须有一个类型是ClassTag[T]的对象。这个ClassTag[T]对象编译器会自动生成,其实就是Class[T]的封装。
看下面的例子:
package cn.byr.nuanyangyang.classtagtest
import java.io.{InputStreamReader, Reader}
import scala.reflect.ClassTag
object ClassTagTest {
class Foo[T: ClassTag] {
private def ctag = implicitly[ClassTag[T]]
def testInstance(obj: AnyRef): Boolean = ctag.runtimeClass.isInstance(obj)
def getClassOfT(): Class[T] = ctag.runtimeClass.asInstanceOf[Class[T]]
}
def main(args: Array[String]): Unit = {
val fooStr = new Foo[String]()
val fooReader = new Foo[Reader]()
val x = "Hello world"
val y = new InputStreamReader(System.in)
println(fooStr.testInstance(x))
println(fooStr.testInstance(y))
println(fooReader.testInstance(x))
println(fooReader.testInstance(y))
println(fooStr.getClassOfT().getCanonicalName())
println(fooReader.getClassOfT().getCanonicalName())
}
}
Foo有一个带ClassTag的泛型参数T。main创建Foo的时候,会隐含地把那个ClassTag[T]对象传给构造函数,本质上还是把T.class传给Foo了。这样,在类里面,可以用implicitly[ClassTag[T]]得到这个隐藏的ClassTag[T]对象。ClassTag[T]的runtimeClass方法得到Java层面的Class[T]对象,这样就能在运行时得到T的类型信息了。
其实Scala在JVM上实现,本质上和Java里传T.class是一样的,但语法漂亮得多。
当然,上述程序的运行结果:
true
false
false
true
java.lang.String
java.io.Reader
【 在 ml3615556 的大作中提到: 】
: [md]
: ```java
: public class SimpleTest {
: ...................
的确哦,不过那个应用场景并不需要实例化,只是需要拿那个class而已,
不过范型的话的确没什么可靠的办法了呢,运行时作为Object,我怎么知道我自己是谁啊,还是老老实实给它传吧。
【 在 nuanyangyang 的大作中提到: 】
: 10年前,Java开发人员设计Java1.5,加入泛型时候,面对了两种选择:
: 1. 重新设计JVM,将泛型作为JVM的特性,但会牺牲向前兼容性。
: 2. 将Java的泛型作为Java语言级的特性,但翻译到JVM bytecode时把泛型参数都擦除(type erasure),这样JVM不会知道泛型的存在,但可以保持兼容Java1.4的bytecode。
: ...................
啊,原来如此被擦掉了呢,它自己都不认识自己那就没办法了。
这张图是暖神自己弄的吧,槽点略多啊,不怕被跨省,不,是跨国么233
另外Duke很萌的,请不要黑他。还有哀乐听着很带感呢而且我竟然听完了。
【 在 mh250303135 的大作中提到: 】
: 你最好把你的需求说一下,不然并不知道你想要做什么
就是“运行时想拿一个范型的具体类”这个代码该怎么写
诶,这个并不是解决不了问题了啦,我把类构造方法改一下主动把类传进来就好了,
只是 Foo<Bar> foo = new Foo<Bar>(Bar.class); 这样写很蠢。。。明明前面都写过一次,然后还得写一次感觉太笨了。
想想是不是有什么更优雅的办法。嘛,如果不行就算了,反正我也很蠢,很多时候2333
【 在 nuanyangyang 的大作中提到: 】
: 顺便来炫耀一下Scala。Scala有一种特殊语法:
: [code=scala]
: class Foo[T: ClassTag]
: ...................
Scala完全不懂哎,听起来很强的样子,大概的意思就是说Scala的范型会隐含的把自己的类的信息带进去(相当于语法层面帮程序员这么做了?)所以运行时就有办法把这些信息拿出来。这种感觉?(歪头~