泛型概念:
- 广泛的类型,在定义一个类的时候,类型中有些方法参数,返回值类型不确定,就使用一个符号,来表示那边尚未确定的类型,这个符号就称之为泛型。
import java.util.ArrayList;
public class Text9 {
public static void main(String[] args) {
//需求:求集合中每个元素的长度
ArrayList list = new ArrayList();
list.add("abc");
list.add(1);
list.add(2.3);
System.out.println(list);//[abc, 1, 2.3]
for (int i = 0; i <list.size() ; i++) {
Object obj = list.get(i);
String str = (String)obj;//向下转换
System.out.println(str.length());
//只能获取“abc”的长度3,int类型的报错,java.lang.ClassCastException 类型转换异常
}
}
}
问题1:
- 存入集合中元素都会向上类型转换成Object类型,当获取该元素并需要使用该元素特有方法时,就必须向下类型转换。
问题2:
- 频繁向上/向下的类型转换,代码繁琐,容易出现类型转换异常。
解决:
- 让集合提供类型检查功能,使用泛型实现。
import java.util.ArrayList;
import java.util.List;
public class Text9 {
public static void main(String[] args) {
//泛型集合:使用泛型技术的集合
List<String> list = new ArrayList();
list.add("abc");
list.add("zzzz");
//list.add(1);类型检测,报错,参数不符合泛型<String>
for (int i = 0; i <list.size() ; i++) {
String s = list.get(i);
System.out.println(s.length());// 3 4
}
System.out.println("==================");
//类似数组
String[] ss = new String[3];//已经确定了数组类型为String
ss[0] = "abcd";
ss[1] = "abcdfg";
//ss[1] = 1; 报错,不兼容的类型: int无法转换为java.lang.String
}
}
泛型集合:
语法:
集合类型<类型> 集合对象名 = new 集合类<>();
集合类:集合框架中的类及其接口,都支持泛型。
<类型>:泛型,类型必须引用类型,如果集合中存在是基本类型的值,泛型必须定义成对应包转类,不能使用基本数据类型。
另外两种泛型集合定义语法:
集合类<类型> 集合对象名 = new 集合类<>(); //称之为泛型菱形技术
集合类<类型> 集合对象名 = new 集合类(); //称之为泛型擦出技术(常用)
泛型类:
概念:
- 定义类时使用泛型技术,该类就是泛型类。
语法;
访问修饰符 class 类名<T......>{
成员属性/方法
}
<T......>:T定义时无法确定类的类型,将类型确定交给调用方。
泛型可以是一个或多个,多个以“,”隔开。
成员属性:属性的类型可以使用 T 来表示。
成员方法:方法的返回值类型,参数类型都可以使用T来表示。
class Source<T>{
//成员属性
private T date;
//成员方法
public T getDate() {
return date;
}
public void setDate(T date) {
this.date = date;
}
private Integer count;//普通成员属性
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}
public class Text10 {
public static void main(String[] args) {
Source<String> s = new Source();
s.setDate("泛型成员属性");
String ss = s.getDate();
System.out.println(ss);//泛型成员属性
Source s2 = new Source();
s2.setCount(10);//普通成员属性
int n = s2.getCount();
System.out.println(n);//10
}
}
特点:
- 由于泛型将类型确定由于定义方转交给调用方,从而让泛型类达到通用效果。
- 如果泛型类,实例化时没有确定具体类型,这时该泛型类的泛型就是Object类型。
- 泛型类中可以有泛型类型属性,可以有普通类型属性。可以有返回值类型是泛型的方法,可以有返回值类型是普通类型的方法。可以有参数类型是泛型的方法,也可以有参数类型是普通类型的方法。
泛型方法
概念:
- 使用与泛型类不一样的泛型作为参数类型的方法。
语法:
访问修饰符 <Q> 返回值类型 方法名(Q q,....){
方法体
}
<Q>:泛型方法的泛型类型,该类型字母要与泛型类字母不同。
该泛型确定通过调用该方法时,提供实际参数来确认。
该实际参数的类型就是泛型的类型。泛型可以是一个或多个,多个以”,”隔开。
class Fx<T>{
T data;
//非静态的泛型方法
public<Q> Q method(Q q){
T a; //非静态的泛型方法中可以使用泛型类的泛型
return q;
}
//静态的泛型方法
public static<Q> Q function(Q q){
//T a; 报错,静态的泛型方法中不能调用泛型类的泛型
//原因:静态方法随着类加载就生成,泛型类的泛型是调用方调用时确定,静态方法早于泛型生成。
return q;
}
}
public class Text11 {
public static void main(String[] args) {
Fx<String> fx = new Fx();
fx.data = "abc";
Integer n = fx.method(1);
}
}
特点:
- 泛型方法的泛型确认,在调用方法时,提供的实际参数来确认,该泛型类型就是实际参数的类型。
- 非静态泛型方法可以使用泛型类的类型,静态泛型方法不可以使用泛型类的类型。
泛型接口:
概念:
- 定义接口使用泛型技术,该接口就是泛型接口
语法:
访问修饰符 interface 接口名<T>{
成员
}
<T>:T定义时无法确定的类型,用于传递泛型。泛型可以是一个或多个,多个以”,”隔开。
interface inter<T>{
//普通接口 = 静态常量 + 抽象方法
//public static T a = 100;报错,静态常量无法使用泛型类的泛型
public T method();
public void function(T t);
}
//多继承,多实现
interface inter2<T> extends inter<T>{
//泛型接口通过继承传递泛型给子接口
}
class Imp<T> implements inter<T>{//泛型接口通过实现传递泛型给实现类
@Override
public T method() {
return null;
}
@Override
public void function(T t) {
}
}
public class Text12 {
public static void main(String[] args) {
Imp<String> imp = new Imp<>();
}
}
特点
- 泛型接口的静态常量成员不能使用泛型类的泛型作为该成员的类型使用
- 泛型接口的抽象方法能使用泛型类的泛型作为返回值类型或参数类型使用。
- 泛型接口通过实现 传递 泛型给实现类
- 泛型接口通过继承 传递 泛型给子接口
泛型通配符
概念:
- 用于接收多个泛型类型的符号
符号:<?>
代码示例
import java.util.ArrayList;
class Person{
private String name;
private int age;
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;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Student extends Person {
public Student(String name, int age) {
super(name, age);
}
@Override
public String toString() {
return "Student{" +
"name='" + super.getName() + '\'' +
", age=" + super.getAge() +
'}';
}
}
class Teacher extends Person{
private String id;
public Teacher(String name, int age,String id) {
super(name, age);
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + super.getName() + '\'' +
", age=" + super.getAge() + '\'' +
", id='" + id + '\'' +
'}';
}
}
public class Text1 {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList();
for (int i = 0; i <2 ; i++) {
list.add(new Student("小明"+i,18+i));
}
ArrayList<Teacher> tlist = new ArrayList();
for (int i = 0; i <2 ; i++) {
tlist.add(new Teacher("老师"+i,28+i,"001"+i));
}
foreach(list);
foreach(tlist);
}
public static void foreach(ArrayList<?> list){//若泛型设置Student,Teacher类就不能使用
System.out.println(list);
}
}
泛型上下限
概念:
- 用于限制具有继承关系的的泛型类型的接收。
泛型上限:<? extends 类名>
泛型下限:<? super 类名>
代码示例
import java.util.ArrayList;
import java.util.List;
class Person{
private String name;
private int age;
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;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Student extends Person{
public Student(String name, int age) {
super(name, age);
}
@Override
public String toString() {
return "Student{" +
"name='" + super.getName() + '\'' +
", age=" + super.getAge() +
'}';
}
}
class Teacher extends Person{
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Teacher(String name, int age, String id) {
super(name, age);
this.id = id;
}
@Override
public String toString() {
return "Teacher{" +
"id='" + id + '\'' +
"name='" + super.getName() + '\'' +
", age=" + super.getAge() +
'}';
}
}
public class Test10 {
public static void foreach(List<? super Student> list) {
System.out.println(list);
}
public static void main(String[] args) {
List<Student> list = new ArrayList();//3个学生集合
//添加十名学生
for (int i = 1 ; i <= 3 ; i++) {
list.add(new Student("小王"+i,19+i));
}
List<Teacher> tlist = new ArrayList();//3个老师集合
for (int i = 1 ; i <= 3 ; i++) {
tlist.add(new Teacher("老王"+i,39+i,"00"+i));
}
List<Person> plist = new ArrayList();//3个人集合
for (int i = 1 ; i <= 3 ; i++) {
plist.add(new Person("隔壁邻居"+i,29+i));
}
foreach(list);
//foreach(tlist);//报错
foreach(plist);
}
}