当前位置:编程学习 > JAVA >>

谈谈java的泛型吧

java的泛型让人很不爽, 看书的时候说:不能干这个,不能干那个。 是不是我太笨? 为什么不能实现一个真泛型? 谁能告诉我如何学好java泛型? Java 泛型 --------------------编程问答-------------------- 泛型很简单呀,很有用的。泛型被称为是 Java 语言走向类型安全的一大步!仔细研究下《java 编程思想》关于泛型的那章!概念上理解起来了能有些困那,动手实践下就很好理解了! --------------------编程问答-------------------- 还是为了定义一种规范,尽量的减少错误的发生。
坚持这种规范还是有必要的。
多写些程序就感觉出来了 --------------------编程问答-------------------- 当你把泛型用于快速排序、归并排序、堆排序、基数排序、自制ArrayList、自制LinkedList、自制HashMap、自制TreeSet的时候,你觉得你学到的算法得到了应用;当你把反射用于自制Hibernate、自制Spring、自制Struts2的时候,你觉得你学到的设计模式得到了运用。总之,Java中的泛型和反射这两个武器,就像C语言中的指针和动态分配内存一样强大。 --------------------编程问答-------------------- 多用你就会了 谁叫java都是别人写好的 。 --------------------编程问答-------------------- 我感觉泛型用着挺爽的 --------------------编程问答-------------------- 为什么java编译器擦除了泛型,却还能在运行时通过Reflection API得到泛型类型信息? --------------------编程问答-------------------- 泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了, --------------------编程问答--------------------
引用 7 楼 sichenglain 的回复:
泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,

你的理解有点简单。 比如说
<T> 
<T extends [Stream]> 
<T super [Stream]> 
<? extends [Stream]> 
<? super [Stream]>
<?>
这些标记的区别是什么?
还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。 --------------------编程问答--------------------
引用 8 楼 gentle_wolf 的回复:
Quote: 引用 7 楼 sichenglain 的回复:

泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,

你的理解有点简单。 比如说
<T> 
<T extends [Stream]> 
<T super [Stream]> 
<? extends [Stream]> 
<? super [Stream]>
<?>
这些标记的区别是什么?
还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。

这些我都知道,只是没有说出来而已,说一点,静态代码区是可以使用泛型的,只是不能把泛型的参数类型作为参数。 --------------------编程问答-------------------- 最重要的原因应该是 byte code 尽量向前兼容。

一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。
谁规定一个语言的泛型实现必须是运行时实现?
谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”?

Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。

看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla……

我想说的是: 你为什么要在运行时取得泛型信息? 
你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗?


也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。

对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。

--------------------编程问答--------------------
引用 10 楼 raistlic 的回复:
最重要的原因应该是 byte code 尽量向前兼容。

一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。
谁规定一个语言的泛型实现必须是运行时实现?
谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”?

Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。

看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla……

我想说的是: 你为什么要在运行时取得泛型信息? 
你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗?


也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。

对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。

别这么极端好吧, 我们只是讨论技术问题。
很多框架设计者需要在运行时获得类型信息,这个你不可否认吧? --------------------编程问答--------------------
引用 11 楼 gentle_wolf 的回复:
Quote: 引用 10 楼 raistlic 的回复:

最重要的原因应该是 byte code 尽量向前兼容。

一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。
谁规定一个语言的泛型实现必须是运行时实现?
谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”?

Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。

看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla……

我想说的是: 你为什么要在运行时取得泛型信息? 
你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗?


也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。

对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。

别这么极端好吧, 我们只是讨论技术问题。
很多框架设计者需要在运行时获得类型信息,这个你不可否认吧?

再说了,每个语言都有自己的优缺点, 这个不是歧视哪个语言, 而是要彻底理解每个语言的优缺点, 好在编程的时候能够知道为什么不让这么做,为什么又需要那么做。
感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 
真的, 别这么认为。 --------------------编程问答--------------------
引用 12 楼 gentle_wolf 的回复:
Quote: 引用 11 楼 gentle_wolf 的回复:

Quote: 引用 10 楼 raistlic 的回复:

最重要的原因应该是 byte code 尽量向前兼容。

一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。
谁规定一个语言的泛型实现必须是运行时实现?
谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”?

Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。

看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla……

我想说的是: 你为什么要在运行时取得泛型信息? 
你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗?


也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。

对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。

别这么极端好吧, 我们只是讨论技术问题。
很多框架设计者需要在运行时获得类型信息,这个你不可否认吧?

再说了,每个语言都有自己的优缺点, 这个不是歧视哪个语言, 而是要彻底理解每个语言的优缺点, 好在编程的时候能够知道为什么不让这么做,为什么又需要那么做。
感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 
真的, 别这么认为。


没觉得极端,就事论事而已。

“感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 ”
我可没这么说,别帮我极端。

Java的泛型实现的确有这样那样的缺点,但总体来说仍然是优秀的语言特性,“假泛型”这种叫法本来就是歧视。

Java有优点也有缺点,有些缺点因为兼容性的问题也许永远不会fix,既然选择Java,那就 live with it. --------------------编程问答--------------------
引用 6 楼 gentle_wolf 的回复:
为什么java编译器擦除了泛型,却还能在运行时通过Reflection API得到泛型类型信息?

很简单啊..你只是在对象的引用上擦除了泛型..但是这个类的信息还是有泛型信息的啊 --------------------编程问答--------------------
引用 9 楼 sichenglain 的回复:
Quote: 引用 8 楼 gentle_wolf 的回复:

Quote: 引用 7 楼 sichenglain 的回复:

泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,

你的理解有点简单。 比如说
<T> 
<T extends [Stream]> 
<T super [Stream]> 
<? extends [Stream]> 
<? super [Stream]>
<?>
这些标记的区别是什么?
还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。

这些我都知道,只是没有说出来而已,说一点,静态代码区是可以使用泛型的,只是不能把泛型的参数类型作为参数。

你说的好像不对吧,可以将泛型类型作为静态方法的参数, 如下:
public static <T extends Comparable<T>> Pair<T> minmax(T[] intAry) {
T min = intAry[0];
T max = min;

for (int i = 0; i < intAry.length; i++) {
if (min.compareTo(intAry[i]) > 0) {
min = intAry[i];
} else if (max.compareTo(intAry[i]) < 0) {
max = intAry[i];
}
}

return new Pair<T>(min, max);
}

但是不能定义泛型静态域,如下:
public static T getSingleton()
{
if(instance != null)
{
return instance;
}

return null;
}

private static T instance;
--------------------编程问答--------------------
引用 15 楼 gentle_wolf 的回复:
Quote: 引用 9 楼 sichenglain 的回复:

Quote: 引用 8 楼 gentle_wolf 的回复:

Quote: 引用 7 楼 sichenglain 的回复:

泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,

你的理解有点简单。 比如说
<T> 
<T extends [Stream]> 
<T super [Stream]> 
<? extends [Stream]> 
<? super [Stream]>
<?>
这些标记的区别是什么?
还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。

这些我都知道,只是没有说出来而已,说一点,静态代码区是可以使用泛型的,只是不能把泛型的参数类型作为参数。

你说的好像不对吧,可以将泛型类型作为静态方法的参数, 如下:
public static <T extends Comparable<T>> Pair<T> minmax(T[] intAry) {
T min = intAry[0];
T max = min;

for (int i = 0; i < intAry.length; i++) {
if (min.compareTo(intAry[i]) > 0) {
min = intAry[i];
} else if (max.compareTo(intAry[i]) < 0) {
max = intAry[i];
}
}

return new Pair<T>(min, max);
}

但是不能定义泛型静态域,如下:
public static T getSingleton()
{
if(instance != null)
{
return instance;
}

return null;
}

private static T instance;
我没说清楚,例如:

        pulbic class A<T>{
     private static T t;
     public void static run(){
     T t;
}
}

这样是不行的,运行时所有的实例都是共享静态的 --------------------编程问答-------------------- 泛型就是限制你输入的类型,多看多练多想 --------------------编程问答-------------------- 1.如果你理解了static在什么加载的,你就会发现,这个行不同是很正常
2.反射的时候,可以得到真的的泛型实例。(我在分页查询的时候,基类中就是使用泛型的方式,提供所有的DAO调用)
  但是我也有很多不清楚的地方(泛型)。前来学习.... --------------------编程问答--------------------
引用 18 楼 cjoy4856 的回复:
1.如果你理解了static在什么加载的,你就会发现,这个行不同是很正常
2.反射的时候,可以得到真的的泛型实例。(我在分页查询的时候,基类中就是使用泛型的方式,提供所有的DAO调用)
  但是我也有很多不清楚的地方(泛型)。前来学习....

我理解了,一切都是因为类型擦除。  --------------------编程问答--------------------
引用 13 楼 raistlic 的回复:
Quote: 引用 12 楼 gentle_wolf 的回复:

Quote: 引用 11 楼 gentle_wolf 的回复:

Quote: 引用 10 楼 raistlic 的回复:

最重要的原因应该是 byte code 尽量向前兼容。

一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。
谁规定一个语言的泛型实现必须是运行时实现?
谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”?

Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。

看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla……

我想说的是: 你为什么要在运行时取得泛型信息? 
你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗?


也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。

对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。

别这么极端好吧, 我们只是讨论技术问题。
很多框架设计者需要在运行时获得类型信息,这个你不可否认吧?

再说了,每个语言都有自己的优缺点, 这个不是歧视哪个语言, 而是要彻底理解每个语言的优缺点, 好在编程的时候能够知道为什么不让这么做,为什么又需要那么做。
感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 
真的, 别这么认为。


没觉得极端,就事论事而已。

“感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 ”
我可没这么说,别帮我极端。

Java的泛型实现的确有这样那样的缺点,但总体来说仍然是优秀的语言特性,“假泛型”这种叫法本来就是歧视。

Java有优点也有缺点,有些缺点因为兼容性的问题也许永远不会fix,既然选择Java,那就 live with it.

还是那句话,我没有说不要live with it,而是要更深入的学习它,学习它为什么要这样。只有这样才能对java理解的更深。不是吗?
比如说我的疑问是: 据说类型擦除是为了向后兼容,为什么? 难道实现了真泛型就不能向后兼容了吗? --------------------编程问答--------------------
引用 3 楼 SmallYamateh 的回复:
当你把泛型用于快速排序、归并排序、堆排序、基数排序、自制ArrayList、自制LinkedList、自制HashMap、自制TreeSet的时候,你觉得你学到的算法得到了应用;当你把反射用于自制Hibernate、自制Spring、自制Struts2的时候,你觉得你学到的设计模式得到了运用。总之,Java中的泛型和反射这两个武器,就像C语言中的指针和动态分配内存一样强大。
请大神指导 具体应该在呢么应用泛型 能详细举例吗
--------------------编程问答--------------------
引用 8 楼 gentle_wolf 的回复:
Quote: 引用 7 楼 sichenglain 的回复:

泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,

你的理解有点简单。 比如说
<T> 
<T extends [Stream]> 
<T super [Stream]> 
<? extends [Stream]> 
<? super [Stream]>
<?>
这些标记的区别是什么?
还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。

不是不能在静态字段使用泛型,是在静态字段要使用泛型 必须自己申明 而不弄使用类的声明而已。因为当类对泛型进行申明的时候,只有在类对象的时候才能确定泛型的类型,而静态字段是属于类的,可以理解为类优先于对象 所以不能这么做 --------------------编程问答--------------------
引用 21 楼 w215230188 的回复:
Quote: 引用 3 楼 SmallYamateh 的回复:

当你把泛型用于快速排序、归并排序、堆排序、基数排序、自制ArrayList、自制LinkedList、自制HashMap、自制TreeSet的时候,你觉得你学到的算法得到了应用;当你把反射用于自制Hibernate、自制Spring、自制Struts2的时候,你觉得你学到的设计模式得到了运用。总之,Java中的泛型和反射这两个武器,就像C语言中的指针和动态分配内存一样强大。
请大神指导 具体应该在呢么应用泛型 能详细举例吗

拿个简单的冒泡来说,就可以进行泛型排序。 --------------------编程问答-------------------- 泛型我也不常用 --------------------编程问答--------------------
引用 22 楼 w215230188 的回复:
Quote: 引用 8 楼 gentle_wolf 的回复:

Quote: 引用 7 楼 sichenglain 的回复:

泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,

你的理解有点简单。 比如说
<T> 
<T extends [Stream]> 
<T super [Stream]> 
<? extends [Stream]> 
<? super [Stream]>
<?>
这些标记的区别是什么?
还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。

不是不能在静态字段使用泛型,是在静态字段要使用泛型 必须自己申明 而不弄使用类的声明而已。因为当类对泛型进行申明的时候,只有在类对象的时候才能确定泛型的类型,而静态字段是属于类的,可以理解为类优先于对象 所以不能这么做

没看明白,能举个例子吗?
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,