泛型方法问题请教

君梦无悔 2017-07-06 03:38:38
各位大神:
正常来说申明定义的一个泛型方法(方法参数是带泛型的),传一个明确泛型类型的变量去调用该泛型方法肯定没问题。
但是,一个方法是非泛型方法,方法参数也是不用带泛型的,奇怪在使用一个带泛型的变量去调用方法,编译为什么能通过?能正常运行。
下面是学习视频例子遇到的问题,就是Utils类里的第二个sort方法(参数Comparator是或不是带泛型的都没问题,疑问在此)
Demo04:
[code=package com.bjsxt.sort.innerType;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

public class Demo04 {
public static void main(String[] args){
Date[] arr = new Date[3];
arr[0] = new Date();
arr[1] = new Date(System.currentTimeMillis()+1000*60*60);
arr[2] = new Date(System.currentTimeMillis()-1000*60*60);
Utils.sort(arr);
System.out.println(Arrays.toString(arr));
String[] arr2 = {"abcd","ab","abc","def"};
Utils.sort(arr2);
System.out.println(Arrays.toString(arr2));
System.out.println("==========List排序============");
List<String> list = new ArrayList<String>();
list.add("abcd");
list.add("ab");
list.add("abc");
list.add("def");
Utils.sort(list);
System.out.println(list);

System.out.println("=============使用Comparator 排序数组===============");
arr2 = new String[] {"a","abcd","abc","def"};
Utils.sort(arr2,new StringComp());
System.out.println(Arrays.toString(arr2));

System.out.println("================List排序+比较器================");
list = new ArrayList<String>();
list.add("abcd");
list.add("a");
list.add("abc");
list.add("def");
Utils.sort(list,new StringComp());
System.out.println(list);//容器可以直接输出
}
}
][/code]
Utils:
package com.bjsxt.sort.innerType;

import java.util.Comparator;
import java.util.List;

public class Utils {
/**
* List的排序+比较器
*/
public static <T> void sort(List<T> list,Comparator<T> com){
//第一步:转成数组
Object[] arr = list.toArray();
sort(arr,com);//试过发现调用的sort方法参数接口Comparator申明不加泛型也能正常运行
//第二步:改变容器中对应的值
for(int i=0;i<arr.length;i++){
list.set(i, (T)arr[i]);
}
}//发现:1.申明要接收泛型,实际未传泛型(未超过申明定义的泛型范围即可吧)。2.申明接收不带泛型的,实际传泛型。这2种都能正常运行,第二种暂不理解。
/**
* 数组的排序(降序)+Comparator接口
*/
public static void sort(Object[] arr,Comparator com){//Comparator檫除,编译时,认为方法需要的是两个Object类对象比较,编译通过。既然编译通过(运行时不用检查了吧),那就能顺利传参调用方法运行,至于运行方法后有问题没得就是后话了。
boolean sorted;
for(int i=arr.length-1;i>0;i--){//依次确定应放在倒数第1 2 3...位置的数(剩最后一个数就不用确定位置了)
sorted = true;
for(int j=0;j<i;j++){
if(com.compare(arr[j], arr[j+1])<0){//此处Object没有compareTo方法,∴需强转为comparable接口型
Object temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
sorted =false;
}
}
if(sorted){//如果一趟也不少,就不会提前退出
break;
}
}
}
}

StringComp:
package com.bjsxt.sort.innerType;
/**
* 排序规则的业务类
*/

public class StringComp implements java.util.Comparator<String>{//Comparator应该还是泛型,实现类StringComp'继承'了一个Comparator指明的类型(应该是进行了内化,StringComp应该就不是泛型了吧。就像新建一个类对象,明确类型并内化吧。)
//泛型在运行期间会被檫除,我想应该是内化了吧。
/**
* 按长度比较大小
* 正数>
* 负数<
* 0==
*/
@Override
public int compare(String o1, String o2) {
int len1 = o1.length();
int len2 = o2.length();
return len1-len2;
}

}
...全文
194 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
君梦无悔 2017-07-06
  • 打赏
  • 举报
回复
引用 5 楼 soton_dolphin 的回复:
举个例子:

    public static void main(String[] args){
		List someObjects = new ArrayList<>();
		someObjects.add("hello");
		someObjects.add(new Integer(4));
		passList(someObjects); //  运行这个方法会抛出异常,因为 integer 没有length 方法
    }

        /* passList 定义的的时候用的泛型String类,这个方法期望传进来的List里面的元素都是字符
         *  因为要和之前的版本兼容,这里的stringList 也可以是raw type也就是没有泛型。
         * 这个 passList 方法只接受两种List, 一种是List, 一种是List<String>       
	private static void passList(List<String> stringList){
		stringList.get(0).length(); //
	}
恩,.get(1).length()会出错。
public class Student1<T> {
	T score;
	public T getScore(){
		return score;
	}
	public Student1(T score){
		this.score = score;
	}
}

public class TestMethod1 {
	public static void main(String[] args){
		Student1<Integer> stu = new Student1<Integer>(15);
//stu是带的泛型指明具体类型的对象
		newScore(stu);
//newScore接收非泛型参数,但调用方法依然顺利运行就是大神说的和之前版本兼容(可以接收泛型/非泛型参数)哈
	}
	public static void newScore(Student1 stu){
		System.out.println((int)stu.getScore()+20);
	}
}
soton_dolphin 2017-07-06
  • 打赏
  • 举报
回复
举个例子:

    public static void main(String[] args){
		List someObjects = new ArrayList<>();
		someObjects.add("hello");
		someObjects.add(new Integer(4));
		passList(someObjects); //  运行这个方法会抛出异常,因为 integer 没有length 方法
    }

        /* passList 定义的的时候用的泛型String类,这个方法期望传进来的List里面的元素都是字符
         *  因为要和之前的版本兼容,这里的stringList 也可以是raw type也就是没有泛型。
         * 这个 passList 方法只接受两种List, 一种是List, 一种是List<String>       
	private static void passList(List<String> stringList){
		stringList.get(0).length(); //
	}
君梦无悔 2017-07-06
  • 打赏
  • 举报
回复
引用 1 楼 soton_dolphin 的回复:
泛型是新的特点,为了能够和之前的java版本兼容,有泛型和没有泛型的方法可以相互调用。泛型是为编译器在编译阶段设计的,为的是能及早发现不兼容的类。在编译器编译完成后,所有的泛型类都会被擦掉,变成Object。你可以研究下java 类型擦除 (Type Erasure)
一个带泛型参数的方法,如果被调用,传来的实参应该是在泛型约束范围内的类型,我是这样想的。∴无泛型实参也可调用带泛型参数方法。但是,一个带泛型实参我认为就不能调用非泛型方法(不能调用参数是非泛型的方法)。
君梦无悔 2017-07-06
  • 打赏
  • 举报
回复
打错了,想说与此同时泛型消失
君梦无悔 2017-07-06
  • 打赏
  • 举报
回复
引用 1 楼 soton_dolphin 的回复:
泛型是新的特点,为了能够和之前的java版本兼容,有泛型和没有泛型的方法可以相互调用。泛型是为编译器在编译阶段设计的,为的是能及早发现不兼容的类。在编译器编译完成后,所有的泛型类都会被擦掉,变成Object。你可以研究下java 类型擦除 (Type Erasure)
终于有人理我,谢谢! 泛型檫除是运行阶段指明是String就是String,指明Integer就是Integer(与此同时泛型小时),而不是Object吗? 调用非泛型方法(方法参数是非泛型变量形参),为什么传泛型变量实参去调用方法,编译阶段还是能通过呢,也能正常运行。
soton_dolphin 2017-07-06
  • 打赏
  • 举报
回复
泛型是新的特点,为了能够和之前的java版本兼容,有泛型和没有泛型的方法可以相互调用。泛型是为编译器在编译阶段设计的,为的是能及早发现不兼容的类。在编译器编译完成后,所有的泛型类都会被擦掉,变成Object。你可以研究下java 类型擦除 (Type Erasure)

51,409

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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