谈谈java的泛型吧

月影 2013-07-17 12:31:04
java的泛型让人很不爽, 看书的时候说:不能干这个,不能干那个。 是不是我太笨? 为什么不能实现一个真泛型? 谁能告诉我如何学好java泛型?
...全文
766 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
kosora曹 2013-08-19
  • 打赏
  • 举报
回复
引用 21 楼 w215230188 的回复:
引用 3 楼 SmallYamateh 的回复:
当你把泛型用于快速排序、归并排序、堆排序、基数排序、自制ArrayList、自制LinkedList、自制HashMap、自制TreeSet的时候,你觉得你学到的算法得到了应用;当你把反射用于自制Hibernate、自制Spring、自制Struts2的时候,你觉得你学到的设计模式得到了运用。总之,Java中的泛型和反射这两个武器,就像C语言中的指针和动态分配内存一样强大。
请大神指导 具体应该在呢么应用泛型 能详细举例吗
拿个简单的冒泡来说,就可以进行泛型排序。
月影 2013-08-19
  • 打赏
  • 举报
回复
引用 22 楼 w215230188 的回复:
[quote=引用 8 楼 gentle_wolf 的回复:] [quote=引用 7 楼 sichenglain 的回复:] 泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,
你的理解有点简单。 比如说 <T> <T extends [Stream]> <T super [Stream]> <? extends [Stream]> <? super [Stream]> <?> 这些标记的区别是什么? 还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。[/quote] 不是不能在静态字段使用泛型,是在静态字段要使用泛型 必须自己申明 而不弄使用类的声明而已。因为当类对泛型进行申明的时候,只有在类对象的时候才能确定泛型的类型,而静态字段是属于类的,可以理解为类优先于对象 所以不能这么做[/quote] 没看明白,能举个例子吗?
静山晚风 2013-08-19
  • 打赏
  • 举报
回复
泛型我也不常用
风程序 2013-08-18
  • 打赏
  • 举报
回复
引用 8 楼 gentle_wolf 的回复:
[quote=引用 7 楼 sichenglain 的回复:] 泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,
你的理解有点简单。 比如说 <T> <T extends [Stream]> <T super [Stream]> <? extends [Stream]> <? super [Stream]> <?> 这些标记的区别是什么? 还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。[/quote] 不是不能在静态字段使用泛型,是在静态字段要使用泛型 必须自己申明 而不弄使用类的声明而已。因为当类对泛型进行申明的时候,只有在类对象的时候才能确定泛型的类型,而静态字段是属于类的,可以理解为类优先于对象 所以不能这么做
风程序 2013-08-18
  • 打赏
  • 举报
回复
引用 3 楼 SmallYamateh 的回复:
当你把泛型用于快速排序、归并排序、堆排序、基数排序、自制ArrayList、自制LinkedList、自制HashMap、自制TreeSet的时候,你觉得你学到的算法得到了应用;当你把反射用于自制Hibernate、自制Spring、自制Struts2的时候,你觉得你学到的设计模式得到了运用。总之,Java中的泛型和反射这两个武器,就像C语言中的指针和动态分配内存一样强大。
请大神指导 具体应该在呢么应用泛型 能详细举例吗
月影 2013-08-18
  • 打赏
  • 举报
回复
引用 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,真心的。
别这么极端好吧, 我们只是讨论技术问题。 很多框架设计者需要在运行时获得类型信息,这个你不可否认吧?[/quote] 再说了,每个语言都有自己的优缺点, 这个不是歧视哪个语言, 而是要彻底理解每个语言的优缺点, 好在编程的时候能够知道为什么不让这么做,为什么又需要那么做。 感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 真的, 别这么认为。[/quote] 没觉得极端,就事论事而已。 “感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 ” 我可没这么说,别帮我极端。 Java的泛型实现的确有这样那样的缺点,但总体来说仍然是优秀的语言特性,“假泛型”这种叫法本来就是歧视。 Java有优点也有缺点,有些缺点因为兼容性的问题也许永远不会fix,既然选择Java,那就 live with it.[/quote] 还是那句话,我没有说不要live with it,而是要更深入的学习它,学习它为什么要这样。只有这样才能对java理解的更深。不是吗? 比如说我的疑问是: 据说类型擦除是为了向后兼容,为什么? 难道实现了真泛型就不能向后兼容了吗?
月影 2013-08-18
  • 打赏
  • 举报
回复
引用 18 楼 cjoy4856 的回复:
1.如果你理解了static在什么加载的,你就会发现,这个行不同是很正常 2.反射的时候,可以得到真的的泛型实例。(我在分页查询的时候,基类中就是使用泛型的方式,提供所有的DAO调用) 但是我也有很多不清楚的地方(泛型)。前来学习....
我理解了,一切都是因为类型擦除。
麦田 2013-08-16
  • 打赏
  • 举报
回复
泛型就是限制你输入的类型,多看多练多想
别看WO太多 2013-08-16
  • 打赏
  • 举报
回复
引用 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的真正类型? 理解了这些才能算真正理解了泛型。[/quote] 这些我都知道,只是没有说出来而已,说一点,静态代码区是可以使用泛型的,只是不能把泛型的参数类型作为参数。[/quote] 你说的好像不对吧,可以将泛型类型作为静态方法的参数, 如下:
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;
[/quote]我没说清楚,例如:

        pulbic class A<T>{
     private static T t;
     public void static run(){
     T t;
}
}
这样是不行的,运行时所有的实例都是共享静态的
cjoy4856 2013-08-16
  • 打赏
  • 举报
回复
1.如果你理解了static在什么加载的,你就会发现,这个行不同是很正常 2.反射的时候,可以得到真的的泛型实例。(我在分页查询的时候,基类中就是使用泛型的方式,提供所有的DAO调用) 但是我也有很多不清楚的地方(泛型)。前来学习....
月影 2013-08-14
  • 打赏
  • 举报
回复
引用 9 楼 sichenglain 的回复:
[quote=引用 8 楼 gentle_wolf 的回复:] [quote=引用 7 楼 sichenglain 的回复:] 泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,
你的理解有点简单。 比如说 <T> <T extends [Stream]> <T super [Stream]> <? extends [Stream]> <? super [Stream]> <?> 这些标记的区别是什么? 还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。[/quote] 这些我都知道,只是没有说出来而已,说一点,静态代码区是可以使用泛型的,只是不能把泛型的参数类型作为参数。[/quote] 你说的好像不对吧,可以将泛型类型作为静态方法的参数, 如下:
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;
terrylmay 2013-07-28
  • 打赏
  • 举报
回复
引用 6 楼 gentle_wolf 的回复:
为什么java编译器擦除了泛型,却还能在运行时通过Reflection API得到泛型类型信息?
很简单啊..你只是在对象的引用上擦除了泛型..但是这个类的信息还是有泛型信息的啊
raistlic 2013-07-26
  • 打赏
  • 举报
回复
最重要的原因应该是 byte code 尽量向前兼容。 一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。 谁规定一个语言的泛型实现必须是运行时实现? 谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”? Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。 看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla…… 我想说的是: 你为什么要在运行时取得泛型信息? 你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗? 也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。 对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。
raistlic 2013-07-26
  • 打赏
  • 举报
回复
引用 12 楼 gentle_wolf 的回复:
[quote=引用 11 楼 gentle_wolf 的回复:] [quote=引用 10 楼 raistlic 的回复:] 最重要的原因应该是 byte code 尽量向前兼容。 一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。 谁规定一个语言的泛型实现必须是运行时实现? 谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”? Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。 看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla…… 我想说的是: 你为什么要在运行时取得泛型信息? 你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗? 也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。 对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。
别这么极端好吧, 我们只是讨论技术问题。 很多框架设计者需要在运行时获得类型信息,这个你不可否认吧?[/quote] 再说了,每个语言都有自己的优缺点, 这个不是歧视哪个语言, 而是要彻底理解每个语言的优缺点, 好在编程的时候能够知道为什么不让这么做,为什么又需要那么做。 感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 真的, 别这么认为。[/quote] 没觉得极端,就事论事而已。 “感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 ” 我可没这么说,别帮我极端。 Java的泛型实现的确有这样那样的缺点,但总体来说仍然是优秀的语言特性,“假泛型”这种叫法本来就是歧视。 Java有优点也有缺点,有些缺点因为兼容性的问题也许永远不会fix,既然选择Java,那就 live with it.
月影 2013-07-26
  • 打赏
  • 举报
回复
引用 11 楼 gentle_wolf 的回复:
[quote=引用 10 楼 raistlic 的回复:] 最重要的原因应该是 byte code 尽量向前兼容。 一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。 谁规定一个语言的泛型实现必须是运行时实现? 谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”? Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。 看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla…… 我想说的是: 你为什么要在运行时取得泛型信息? 你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗? 也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。 对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。
别这么极端好吧, 我们只是讨论技术问题。 很多框架设计者需要在运行时获得类型信息,这个你不可否认吧?[/quote] 再说了,每个语言都有自己的优缺点, 这个不是歧视哪个语言, 而是要彻底理解每个语言的优缺点, 好在编程的时候能够知道为什么不让这么做,为什么又需要那么做。 感觉你的意思就是,java很优秀, 你认为java有缺点,那不是java的问题,是你自己的问题。 真的, 别这么认为。
月影 2013-07-26
  • 打赏
  • 举报
回复
引用 10 楼 raistlic 的回复:
最重要的原因应该是 byte code 尽量向前兼容。 一直觉得 “真泛型” “假泛型” 是C程序员带有偏见的命名方式。 谁规定一个语言的泛型实现必须是运行时实现? 谁规定运行时携带类型信息就是所谓“真泛型”,否则就是所谓“假泛型”? Java 的泛型机制设计之初就是以编译为界限,如果你感觉到局限,那是你自己对泛型机制的定位有问题。 看过很多类似 "why java generics suck" 的文章,一般主要都是说,你在运行时无法取得泛型信息,blablabla…… 我想说的是: 你为什么要在运行时取得泛型信息? 你的设计有问题 / 你对Java泛型的定位有问题 / 你这时候如果要做类型检查,假如类型不符合,你除了抛出/处理运行时异常还能做什么?——你直接去cast就是了 / 就算给你拿到泛型信息,你又能用它们做什么?你要做的事,没有泛型真的不能做吗? 也有人无奈之下就拿效率来说事了,这没什么好争的,在效率方面,Java泛型利大于弊,编译时类型检查 > 运行时类型检查。 对于纠结自动装箱/拆箱效率问题的,我只想说: 用C++去吧,别用Java,真心的。
别这么极端好吧, 我们只是讨论技术问题。 很多框架设计者需要在运行时获得类型信息,这个你不可否认吧?
月影 2013-07-24
  • 打赏
  • 举报
回复
引用 7 楼 sichenglain 的回复:
泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,
你的理解有点简单。 比如说 <T> <T extends [Stream]> <T super [Stream]> <? extends [Stream]> <? super [Stream]> <?> 这些标记的区别是什么? 还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。
别看WO太多 2013-07-24
  • 打赏
  • 举报
回复
引用 8 楼 gentle_wolf 的回复:
[quote=引用 7 楼 sichenglain 的回复:] 泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,
你的理解有点简单。 比如说 <T> <T extends [Stream]> <T super [Stream]> <? extends [Stream]> <? super [Stream]> <?> 这些标记的区别是什么? 还有 为什么不能用new T(), 为什么不能在静态字段中使用泛型? 能不能在反射中得到T的真正类型? 理解了这些才能算真正理解了泛型。[/quote] 这些我都知道,只是没有说出来而已,说一点,静态代码区是可以使用泛型的,只是不能把泛型的参数类型作为参数。
别看WO太多 2013-07-23
  • 打赏
  • 举报
回复
泛型很简单啊,就是写的加个尖括号,写上你要添加进去的类型,让编译器验证就行了,
月影 2013-07-22
  • 打赏
  • 举报
回复
为什么java编译器擦除了泛型,却还能在运行时通过Reflection API得到泛型类型信息?
加载更多回复(5)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧