当前位置: 首页 > news >正文

吉安市城乡规划建设局网站广告代理公司

吉安市城乡规划建设局网站,广告代理公司,上海百度移动关键词排名优化,小程序制作代码编写泛型JDK1.5设计了泛型的概念。泛型即为“类型参数”,这个类型参数在声明它的类、接口或方法中,代表未知的通用的类型。例如:java.lang.Comparable接口和java.util.Comparator接口,是用于对象比较大小的规范接口,这两个…

泛型

JDK1.5设计了泛型的概念。泛型即为“类型参数”,这个类型参数在声明它的类、接口或方法中,代表未知的通用的类型。例如:

java.lang.Comparable接口和java.util.Comparator接口,是用于对象比较大小的规范接口,这两个接口只是限定了当一个对象大于另一个对象时返回正整数,小于返回负整数,等于返回0。但是并不确定是什么类型的对象比较大小,之前的时候只能用Object类型表示,使用时既麻烦又不安全,因此JDK1.5就给它们增加了泛型。

public interface Comparable<T>{int compareTo(T o) ;
}
public interface Comparator<T>{int compare(T o1, T o2) ;
}

其中<T>就是类型参数,即泛型。

泛型的好处

那么我们在使用如上面这样的接口时,如果没有泛型或不指定泛型,很麻烦,而且有安全隐患。如果有了泛型并使用泛型,那么既能保证安全,又能简化代码。

JavaBean:圆类型

class Circle{private double radius;public Circle(double radius) {super();this.radius = radius;}public double getRadius() {return radius;}public void setRadius(double radius) {this.radius = radius;}@Overridepublic String toString() {return "Circle [radius=" + radius + "]";}}

比较器

import java.util.Comparator;public class CircleComparator implements Comparator{@Overridepublic int compare(Object o1, Object o2) {//强制类型转换Circle c1 = (Circle) o1;Circle c2 = (Circle) o2;return Double.compare(c1.getRadius(), c2.getRadius());}}

测试类

public class TestGeneric {public static void main(String[] args) {CircleComparator com = new CircleComparator();System.out.println(com.compare(new Circle(1), new Circle(2)));System.out.println(com.compare("圆1", "圆2"));//运行时异常:ClassCastException}
}

使用泛型:

比较器:

class CircleComparator implements Comparator<Circle>{@Overridepublic int compare(Circle o1, Circle o2) {//不再需要强制类型转换,代码更简洁return Double.compare(o1.getRadius(), o2.getRadius());}}

测试类

import java.util.Comparator;public class TestGeneric {public static void main(String[] args) {CircleComparator com = new CircleComparator();System.out.println(com.compare(new Circle(1), new Circle(2)));//        System.out.println(com.compare("圆1", "圆2"));//编译错误,因为"圆1", "圆2"不是Circle类型,编译器提前报错,而不是冒着风险在运行时再报错}
}

其中:<T>是类型变量(Type Variables),Comparator<T>这种就称为参数化类型(Parameterized Types),Comparator<Circle>中的<Circle>是参数化类型的类型参数<Type Arguments of Parameterized Types>。

类比方法的参数,我们可以把<T>,称为类型形参,将<Circle>称为类型实参,有助于我们理解泛型。 

参数类型:泛型类与泛型接口

当我们在声明类或接口时,类或接口中定义某个成员时,该成员有些类型是不确定的,而这个类型需要在使用这个类或接口时才可以确定,那么我们可以使用泛型。

声明泛型类与泛型接口

语法格式:

【修饰符】 class 类名<类型变量列表>{}
【修饰符】 interface 接口名<类型变量列表>{}
<类型变量列表>:可以是一个或多个类型变量,一般都是使用单个的大写字母表示。例如:<T>、<K,V>等。
<类型变量列表>中的类型变量不能用于静态成员上。

示例代码:

例如:我们要声明一个学生类,该学生包含姓名、成绩,而此时学生的成绩类型不确定,为什么呢,因为,语文老师希望成绩是“优秀”、“良好”、“及格”、“不及格”,数学老师希望成绩是89.5, 65.0,英语老师希望成绩是'A','B','C','D','E'。那么我们在设计这个学生类时,就可以使用泛型。

public class Student<T>{private String name;private T score;public Student() {super();}public Student(String name, T score) {super();this.name = name;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public T getScore() {return score;}public void setScore(T score) {this.score = score;}@Overridepublic String toString() {return "姓名:" + name + ", 成绩:" + score;}
}
使用泛型类与泛型接口

在使用这种参数化的类与接口时,我们需要指定泛型变量的实际类型参数:

(1)实际类型参数必须是引用数据类型,不能是基本数据类型

(2)在创建类的对象时指定类型变量对应的实际类型参数

public class TestGeneric{public static void main(String[] args) {//语文老师使用时:Student<String> stu1 = new Student<String>("张三", "良好");//数学老师使用时://Student<double> stu2 = new Student<double>("张三", 90.5);//错误,必须是引用数据类型Student<Double> stu2 = new Student<Double>("张三", 90.5);//英语老师使用时:Student<Character> stu3 = new Student<Character>("张三", 'C');//错误的指定//Student<Object> stu = new Student<String>();//错误的}
}
JDK1.7支持简写形式:Student<String> stu1 = new Student<>("张三", "良好");
指定泛型实参时,必须左右两边一致,不存在多态现象

(3)在继承泛型类或实现泛型接口时,指定类型变量对应的实际类型参数

class ChineseStudent extends Student<String>{public ChineseStudent() {super();}public ChineseStudent(String name, String score) {super(name, score);}}
public class TestGeneric{public static void main(String[] args) {//语文老师使用时:ChineseStudent stu = new ChineseStudent("张三", "良好");}
}
class Circle implements Comparable<Circle>{private double radius;public Circle(double radius) {super();this.radius = radius;}public double getRadius() {return radius;}public void setRadius(double radius) {this.radius = radius;}@Overridepublic String toString() {return "Circle [radius=" + radius + "]";}@Overridepublic int compareTo(Circle c){return Double.compare(radius,c.radius);}}
类型变量的上限

当在声明类型变量时,如果不希望这个类型变量代表任意引用数据类型,而是某个系列的引用数据类型,那么可以设定类型变量的上限。

语法格式:

<类型变量  extends 上限>

如果有多个上限

<类型变量  extends 上限1 & 上限2>
如果多个上限中有类有接口,那么只能有一个类,而且必须写在最左边。接口的话,可以多个。
如果在声明<类型变量>时没有指定任何上限,默认上限是java.lang.Object。

例如:我们要声明一个两个数求和的工具类,要求两个加数必须是Number数字类型,并且实现Comparable接口。

class SumTools<T extends Number & Comparable<T>>{private T a;private T b;public SumTools(T a, T b) {super();this.a = a;this.b = b;}@SuppressWarnings("unchecked")public T getSum(){if(a instanceof BigInteger){return (T) ((BigInteger) a).add((BigInteger)b);}else if(a instanceof BigDecimal){return (T) ((BigDecimal) a).add((BigDecimal)b);}else if(a instanceof Short){return (T)(Integer.valueOf((Short)a+(Short)b));}else if(a instanceof Integer){return (T)(Integer.valueOf((Integer)a+(Integer)b));}else if(a instanceof Long){return (T)(Long.valueOf((Long)a+(Long)b));}else if(a instanceof Float){return (T)(Float.valueOf((Float)a+(Float)b));}else if(a instanceof Double){return (T)(Double.valueOf((Double)a+(Double)b));}throw new UnsupportedOperationException("不支持该操作");}
}

测试类

    public static void main(String[] args) {SumTools<Integer> s = new SumTools<Integer>(1,2);Integer sum = s.getSum();System.out.println(sum);//        SumTools<String> s = new SumTools<String>("1","2");//错误,因为String类型不是extends Number}
泛型擦除

当使用参数化类型的类或接口时,如果没有指定泛型,那么会怎么样呢?

会发生泛型擦除,自动按照最左边的第一个上限处理。如果没有指定上限,上限即为Object。

    public static void main(String[] args) {SumTools s = new SumTools(1,2);Number sum = s.getSum();System.out.println(sum);}
import java.util.Comparator;public class CircleComparator implements Comparator{@Overridepublic int compare(Object o1, Object o2) {//强制类型转换Circle c1 = (Circle) o1;Circle c2 = (Circle) o2;return Double.compare(c1.getRadius(), c2.getRadius());}}
public class TestExer1 {public static void main(String[] args) {Coordinate<String> c1 = new Coordinate<>("北纬38.6", "东经36.8");System.out.println(c1);//        Coordinate<Double> c2 = new Coordinate<>(38.6, 38);//自动装箱与拆箱只能与对应的类型 38是int,自动装为IntegerCoordinate<Double> c2 = new Coordinate<>(38.6, 36.8);System.out.println(c2);}
}
class Coordinate<T>{private T x;private T y;public Coordinate(T x, T y) {super();this.x = x;this.y = y;}public Coordinate() {super();}public T getX() {return x;}public void setX(T x) {this.x = x;}public T getY() {return y;}public void setY(T y) {this.y = y;}@Overridepublic String toString() {return "Coordinate [x=" + x + ", y=" + y + "]";}}

泛型方法

前面介绍了在定义类、接口时可以声明<类型变量>,在该类的方法和属性定义、接口的方法定义中,这些<类型变量>可被当成普通类型来用。但是,在另外一些情况下,

(1)如果我们定义类、接口时没有使用<类型变量>,但是某个方法定义时,想要自己定义<类型变量>;

(2)另外我们之前说类和接口上的类型形参是不能用于静态方法中,那么当某个静态方法想要定义<类型变量>。

那么,JDK1.5之后,还提供了泛型方法的支持。

语法格式:

【修饰符】 <类型变量列表> 返回值类型 方法名(【形参列表】)【throws 异常列表】{//...
}
<类型变量列表>:可以是一个或多个类型变量,一般都是使用单个的大写字母表示。例如:<T>、<K,V>等。
<类型变量>同样也可以指定上限

示例代码:

我们编写一个数组工具类,包含可以给任意对象数组进行从小到大排序,要求数组元素类型必须实现Comparable接口

public class MyArrays{public static <T extends Comparable<T>> void sort(T[] arr){for (int i = 1; i < arr.length; i++) {for (int j = 0; j < arr.length-i; j++) {if(arr[j].compareTo(arr[j+1])>0){T temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}}
}

测试类

public class TestGeneric{public static void main(String[] args) {int[] arr = {3,2,5,1,4};
//        MyArrays.sort(arr);//错误的,因为int[]不是对象数组String[] strings = {"hello","java","chai"};MyArrays.sort(strings);System.out.println(Arrays.toString(strings));Circle[] circles = {new Circle(2.0),new Circle(1.2),new Circle(3.0)};MyArrays.sort(circles);System.out.println(Arrays.toString(circles));}
}

类型通配符

当我们声明一个方法时,某个形参的类型是一个参数化的泛型类或泛型接口类型,但是在声明方法时,又不确定该泛型实际类型,我们可以考虑使用类型通配符。

<?>任意类型

例如:我们要声明一个学生管理类,这个管理类要包含一个方法,可以遍历学生数组。

学生管理类:

class StudentService {public static void print(Student<?>[] arr) {for (int i = 0; i < arr.length; i++) {System.out.println(arr[i]);}}
}

测试类

public class TestGeneric {public static void main(String[] args) {// 语文老师使用时:Student<String> stu1 = new Student<String>("张三", "良好");// 数学老师使用时:// Student<double> stu2 = new Student<double>("张三", 90.5);//错误,必须是引用数据类型Student<Double> stu2 = new Student<Double>("张三", 90.5);// 英语老师使用时:Student<Character> stu3 = new Student<Character>("张三", 'C');Student<?>[] arr = new Student[3];arr[0] = stu1;arr[1] = stu2;arr[2] = stu3;StudentService.print(arr);}
}
<? extends 上限>

例如:我们要声明一个学生管理类,这个管理类要包含一个方法,找出学生数组中成绩最高的学生对象。

要求学生的成绩的类型必须可比较大小,实现Comparable接口。

学生管理类:

class StudentService {@SuppressWarnings({ "rawtypes", "unchecked" })public static Student<? extends Comparable> max(Student<? extends Comparable>[] arr){Student<? extends Comparable> max = arr[0];for (int i = 0; i < arr.length; i++) {if(arr[i].getScore().compareTo(max.getScore())>0){max = arr[i];}}return max;}
}

测试类

public class TestGeneric {@SuppressWarnings({ "rawtypes", "unchecked" })public static void main(String[] args) {Student<? extends Double>[] arr = new Student[3];arr[0] = new Student<Double>("张三", 90.5);arr[1] = new Student<Double>("李四", 80.5);arr[2] = new Student<Double>("王五", 94.5);Student<? extends Comparable> max = StudentService.max(arr);System.out.println(max);}
}
<? super 下限>

现在要声明一个数组工具类,包含可以给任意对象数组进行从小到大排序,只要你指定定制比较器对象,而且这个定制比较器对象可以是当前数组元素类型自己或其父类的定制比较器对象

数组工具类:

class MyArrays{public static <T> void sort(T[] arr, Comparator<? super T> c){for (int i = 1; i < arr.length; i++) {for (int j = 0; j < arr.length-i; j++) {if(c.compare(arr[j], arr[j+1])>0){T temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}}
}

例如:有如下JavaBean

class Person{private String name;private int age;public Person(String name, int age) {super();this.name = name;this.age = age;}public Person() {super();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "name=" + name + ", age=" + age;}
}
class Student extends Person{private int score;public Student(String name, int age, int score) {super(name, age);this.score = score;}public Student() {super();}public int getScore() {return score;}public void setScore(int score) {this.score = score;}@Overridepublic String toString() {return super.toString() + ",score=" + score;}}

测试类

public class TestGeneric {public static void main(String[] args) {Student[] all = new Student[3];all[0] = new Student("张三", 23, 89);all[1] = new Student("李四", 22, 99);all[2] = new Student("王五", 25, 67);MyArrays.sort(all, new Comparator<Person>() {@Overridepublic int compare(Person o1, Person o2) {return o1.getAge() - o2.getAge();}});System.out.println(Arrays.toString(all));MyArrays.sort(all, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getScore() - o2.getScore();}});System.out.println(Arrays.toString(all));}
}

使用类型通配符来指定类型参数的问题

<?>:不可变,因为<?>类型不确定,编译时,任意类型都是错

<? extends 上限>:不可变,因为<? extends 上限>的?可能是上限或上限的子类,即类型不确定,编译按任意类型处理都是错。

<? super 下限>:可以将值修改为下限或下限子类的对象,因为<? super 下限>?代表是下限或下限的父类,那么设置为下限或下限子类的对象是安全的。

public class TestGeneric {public static void main(String[] args) {Student<?> stu1 = new Student<>();stu1.setScore(null);//除了null,无法设置为其他值Student<? extends Number> stu2 = new Student<>();stu2.setScore(null);//除了null,无法设置为其他值Student<? super Number> stu3 = new Student<>();stu3.setScore(56);//可以设置Number或其子类的对象}
}
class Student<T>{private String name;private T score;public Student() {super();}public Student(String name, T score) {super();this.name = name;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public T getScore() {return score;}public void setScore(T score) {this.score = score;}@Overridepublic String toString() {return "姓名:" + name + ", 成绩:" + score;}
}

http://www.khdw.cn/news/20133.html

相关文章:

  • 编程入门自学网站目前最火的推广平台
  • 家具网站设计方案潍坊网站建设公司
  • 汉狮做网站公司郑州百度指数分析官网
  • 河北提供网站制作公司哪家好南宁seo多少钱报价
  • 福州建设项目管理公司seo技术优化整站
  • 51建模网官方网站推广衣服的软文
  • 可以做外链的网站竞价排名采用什么计费方式
  • 私人衣橱网站建设a5站长网网站交易
  • 天津电子商务网站网推资源渠道
  • 网页模板免费下载网页模板下载班级优化大师app
  • 网站制作需要什么软件有哪些葫岛百度seo
  • 怎么用微信官方网站做二维码百度关键字优化
  • 学做网网站论坛营销计划书7个步骤
  • 最好的商业网站中国域名网官网
  • 网站内容该怎么做百度推广员工工资怎么样
  • 可做设计任务的网站网站制作 网站建设
  • 博彩网站如何做的充值网络优化师
  • 盱眙网站制作武汉网站推广排名
  • 南通专业网站排名推广广告推广平台赚取佣金
  • 代理服务网站网络营销概念是什么
  • 暖通毕业设计代做网站百度竞价推广代运营
  • 镇江集团网站建设求好用的seo软件
  • 中国人在俄罗斯做网站需要多少卢布网络营销所学课程
  • c2c网站名称和网址全球新冠疫情最新消息
  • 漯河做网站zrgu整站优化代理
  • 东莞公司网站价格网站关键词排名快速提升
  • wordpress搜索收录谷歌优化的网络公司
  • 永久网站建设教程网站推广公司电话
  • 个人网站怎么做引流营销方案怎么写?
  • 网站模板 家武汉大学人民医院光谷院区