泛型类接口方法学习

一、泛型

1 概念

泛型(Generics),广泛的类型。最大用途是给集合容器添加标签,让开发人员知道容器里面放到是什么类型,并且自动对放入集合的元素进行类型检查。

类比实参和形参,我们在对方法中的变量操作时,并没有指明变量的实际大小,而是使用变量名来指代。泛型就是这个情况下诞生的,通过符号来指代类型,等方法调用传入实参时才会明确具体类型。

//当使用这个类时,再指明T的类型
class MyClass<T>{
	T obj;

	public T getObj(){
		return obj;
	}
	
	public void setObj(T obj){
		this.obj = obj;
	}
}

public class Demo{
	public static void main(){
		//指明类型是String
		MyClass<String> stringClass = new MyClass<>();
		//指明类型是Double
		MyClass<Double> stringClass = new MyClass<>();
		//指明类型是Integer
		MyClass<Integer> stringClass = new MyClass<>();
	}
}

总的来说,泛型就是一个参数,是类型的参数。泛型的作用:把运行时可能存在的强制类型转换风险提前到编译期解决,并简化了代码。

2 声明位置和使用位置

  • 泛型类
    • 声明位置:类名 <T>
    • 可以使用的位置:
      • 成员变量类型
      • 非静态成员方法的返回值类型
      • 非静态成员方法的参数类型
  • 泛型接口
    • 声明位置:接口名 <T>
    • 两种使用情况:
      • class ClassA implements 接口名<类型名称>, 实现类不再是泛型类
      • class ClassB<T> implements 接口名<T>, 实现类还是泛型类
  • 泛型方法
    • 声明位置:public static <T> 返回值类型 方法名(T t)
    • 使用位置:只能在方法域内部使用
    • 示例:public static <T> T show(T t) : 传入什么类型,就返回什么类型

3 使用的注意事项

  • 静态域内部不能使用泛型
  • 使用泛型类时,必须明确泛型类型
  • 使用泛型对象时,可以省略右边的泛型类型,但是不能少了<>
  • 如果使用泛型类时没有指明类型,默认是Object类型

4 通配符

  • <?> 表示任意的泛型类型
    跟原先的T有些区别,原先的T的类型对应的是调用时传入的类型。方法泛型需要再返回值前面定义。即public static <T> 返回值类型 方法名(T t),所以T类似于一个中转站。
  • <? extends A> 设定类需要继承父类A,即上限
  • <? super B> 设定类需要是子类B的父类,即下限

应用场景:

  • 设置下限:最小也肯定是动物。最大可能是Object。通常用于添加数组,不适合获取数据
void test1(List<? super Animal> list){
	//适合添加数据
	list.add(new Animal());
	list.add(new Cat())
	//不适合获取,得到数据后也要强制类型转换
	Object o = list.get(0);
}
  • 设置上限:获取到的肯定是动物的子类,最大也是动物类
void test1(List<? extends Animal> list){
	//适合获取数据
	Animal a = list.get(0);
	//不能添加数据
	list.add(new );//无法确定添加什么类型的数据
}
  • <?>不适合获取,也不能添加,通常用于翻转,复制等操作。

5 通配符<?>和泛型参数T的区别

通配符<?>和泛型参数T的区别在于使用的场景和限制。 通配符<?>是一种不确定的类型,可以用来表示任意类型。它可以在方法的参数和返回值类型中使用,用来增加灵活性,使方法可以接受不同类型的参数。
泛型参数T是一种确定的类型,可以在类、方法、接口等定义中使用,用来指定某种具体的类型。它可以使代码更加安全和类型正确,并提供编译时的类型检查。

具体区别如下:

  1. 使用范围:通配符<?>可以在方法的参数和返回值类型中使用,可以接受不同类型的参数。而泛型参数T可以在类、方法、接口等定义中使用,用来指定某种具体的类型。
  2. 灵活性:通配符<?>可以接受任意类型的参数,因此在方法的定义中可以处理多种不同类型的参数。而泛型参数T是一种确定的类型,只能处理指定的类型。
  3. 类型推断:通配符<?>在方法调用时无法推断具体的类型,需要手动指定或进行类型转换。而泛型参数T在方法调用时可以根据实际参数类型自动推断具体的类型,不需要手动指定。
  4. 限制:通配符<?>无法获取具体的类型信息,只能进行简单的操作。而泛型参数T可以通过反射等方式获取具体的类型信息,进行更复杂的操作。

总之,通配符<?>和泛型参数T在使用场景、灵活性和类型推断等方面有所不同。选择使用哪种方式取决于具体的需求和代码逻辑。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
3. 主动抛出异常 下面是一个简单的示例代码,定义了一个自定义异常类 `MyException`,在 `main()` 方法中使用 `throw` 关键字抛出异常: ```java public class ExceptionDemo { public static void main(String[] args) { try { throw new MyException("抛出自定义异常"); } catch (MyException e) { System.out.println(e.getMessage()); } } static class MyException extends Exception { public MyException(String message) { super(message); } } } ``` 4. 类定义与方法的调用 下面是一个简单的类 `MyGenericClass` 的示例代码,包含了一个方法 `printArray()`,可以输出数组中的元素: ```java public class GenericDemo { public static void main(String[] args) { Integer[] intArray = { 1, 2, 3 }; String[] strArray = { "a", "b", "c" }; MyGenericClass<Integer> intClass = new MyGenericClass<>(intArray); MyGenericClass<String> strClass = new MyGenericClass<>(strArray); intClass.printArray(); strClass.printArray(); } } class MyGenericClass<T> { private T[] array; public MyGenericClass(T[] array) { this.array = array; } public void printArray() { for (T element : array) { System.out.print(element + " "); } System.out.println(); } } ``` 在 `main()` 方法中创建了一个 `MyGenericClass` 的对象,分别传入了 `Integer` 和 `String` 类的数组,并调用了方法 `printArray()`,输出了数组中的元素。 5. 内部类 下面是一个简单的示例代码,定义了一个 `School` 类和一个 `Student` 内部类,创建了一个 `School` 对象和一个 `Student` 对象,并访问了它们的方法: ```java public class InnerClassDemo { public static void main(String[] args) { School school = new School(); School.Student student = school.new Student("小明"); student.study(); } static class School { class Student { private String name; public Student(String name) { this.name = name; } public void study() { System.out.println(name + "在学习"); } } } } ``` 在 `main()` 方法中创建了一个 `School` 对象和一个 `Student` 对象,并调用了 `Student` 内部类中的 `study()` 方法,输出了 `小明在学习`。 6. Lambda 表达式 下面是一个简单的示例代码,定义了一个接口 `MyInterface`,并使用 Lambda 表达式实现了它的方法: ```java public class LambdaDemo { public static void main(String[] args) { MyInterface myInterface = (x, y) -> x + y; System.out.println(myInterface.add(1, 2)); } interface MyInterface { int add(int x, int y); } } ``` 在 `main()` 方法中使用 Lambda 表达式实现了 `MyInterface` 接口的 `add()` 方法,输出了 `3`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值