书里面这么写的:
public class Singleton<T>
{
private static T singleInstance //ERROR
private static T getSingleInstance() //ERROR
{
if(singleInstance == null)
return singleInstance;
}
}
类型擦除后,只剩下 Singleton 类,它只包含一个 singleInstance 域。因此,禁止使用带有类型变量的静态域和方法。
不太理解什么意思,为什么跟类型擦除有关系?请高手指点一下
1
ipeony 2016-02-24 10:09:10 +08:00 1
初始化顺序问题吧
|
2
fwrq41251 2016-02-24 10:12:59 +08:00 1
泛型类上的泛型类型在实例化时确定。
比如: Singleton<String> singletonForString= new Singleton(); Singleton<Boolean> singletonForBoolean= new Singleton(); 而静态成员是被该类的所有对象共享的,显然你的泛型类型不能应用到静态成员上。 |
3
sadwxds 2016-02-24 10:17:47 +08:00 1
我是这么想的,如果你的泛型能够用在静态的属性或方法中。
那么你在 A 处 new Singleton<Integer>; B 处 new Singleton<YouClass>; 那么当你调用 Singleton.getSingleInstance(); 你知道你将要返回的是什么样的类型结果吗? |
4
yrom 2016-02-24 10:26:22 +08:00 1
类( Class )的类型参数( Type Parameters )只存在于类的实例的方法域和成员变量域。换句话说,必须实例化你这个类( Singleton )才知道那个类型参数“ T ”是什么鬼。 再比如, new Singleton<String>() , 这个时候"T"就是 String 。不知道明白了没。。
|
5
SoloCompany 2016-02-24 10:47:36 +08:00 1
看你怎么理解, static 不能使用模板类型可以说和类型擦除有关也可以说无关
具体到 java 泛型里面主要在于模板类型 T 的作用范围,本身规定就只是成员(变量以及方法) 静态变量的作用范围完全不一样,所以不能使用模板类型 从这一点上来说,可以说和类型擦除不一定相关 但如果考虑到实现机制的话,就有可能相关,泛型有一种实现机制就是生成模板衍生类 比如你举的这个例子 Singleton<T> 对应的是一个独立的衍生类 Singleton_T 如果静态变量也复制一份的话,那么静态方法 /变量就可以使用模板类型 就是说 Singleton<A>.singleInstance 和 Singleton<B>.singleInstance 可以不一样(被复制) Java 的泛型机制是类型擦除机制,无论怎么实现都不可能有复制的静态变量,所以任意静态元素都不可以使用类定义的模板类型,因为他们之间毫无关系。你这么理解,静态变量以及方法和方法和他们所依附( enclosing )的类之间是完全没有关系的,他们只是简单的被放在一起而已 |
6
SoloCompany 2016-02-24 10:50:45 +08:00
我觉得 Kotlin 把 static 关键字去除了是一个比较明智的选择
因为 static 的确是不太 OO 的,而且会造成有些概念上的混淆 用 package function 以及 compainion objet 来代替还是挺适合的 |
7
cmuler OP @SoloCompany 用模板类来实现泛型应该是 c#的实现方式吧。请教一下,这两种实现方式哪种更加好一点
|
8
wizardforcel 2016-02-24 13:13:02 +08:00 via Android
泛型的类型参数只在编译时存在,编译之后会被擦除。比如你的 Singleton<String>和 Singleton<Integer>编译之后都是 Singleton , T 会变成 Object 。你是希望 Singleton<String>和 Singleton<Integer>有不同的 instance ,但实际上它们是冲突的,为了避免这种情况所以不能这么写。
|
9
SoloCompany 2016-02-24 13:58:41 +08:00
@cmuler 模板衍生类互相之间没有一个公共的基类,类型不相容(更别谈赋值相容了),并且类的数量不好彩的话会爆炸(要知道泛型是嵌套的,考虑一下 List<List<List<Map<?,?>>>>)
其实这点内存占用还不是最要命的,最要命的是没有公共基类了,就别想有任何兼容性可言了,也就是说,之前已经写好的(包括大量第三方)类库,都无法使用泛型版本的类,除非改写为只适用于某特定泛型版本的。 Java 里面也有这样的例子,你看一眼 java.uitil.Arrays 的实现就知道了,就是一个典型的模板方式实现的泛型,因为基本类型不是 Object 。 其实 java 也可以创造一种模板方式的泛型语法,比如增加一个关键字 template , Arrays.binarySearch 就可以这样定义 public static <template t> binarySearch(t[] a, t key); 然后让编译器来动态生成每一种类型对应的方法 可以说这两种泛型完全是不同的概念 |