注解:
用于在代码中插入元数据,不会直接影响程序的执行,但可以被编译器、开发工具或运行时环境用来处理特定任务,如编译时检查、生成额外的代码、进行框架级配置等。
- 预定义注解:java给的,例如:@Override:用于标记一个方法是重写父类的方法。
- 自定义注解
- 元注解:注解其他注解的注解。
元数据:关于数据的数据,提供了描述或解释其他数据的信息,包括但不限于数据库、文档管理、编译器、网络协议和编程语言中的注解等。在Java中,注解是元数据的一种形式。它们为代码提供附加信息,但这些信息不直接影响代码的执行
元数据的作用:
- 描述数据:提供关于数据的详细信息,例如类型、格式、长度等。
- 数据管理:帮助组织和管理数据,便于查找和使用。
- 提高可读性:提供额外的信息,使代码更加清晰和易于理解。
- 自动化处理:支持自动化工具和框架进行数据处理,例如代码生成、依赖注入、数据验证等。
元数据在其他领域的应用:
- 数据库:数据库中的元数据描述了表、列、数据类型、索引等信息。
- 文档管理:文档元数据可以包括标题、作者、创建日期、关键词等。
- 网络协议:网络协议中的元数据可能描述了数据包的长度、来源、目的地等信息。
参考:Java 中的泛型(两万字超全详解)_java 泛型-CSDN博客
泛型:
参数化类型,即允许类、接口和方法定义中使用类型参数,这些类型参数在实际使用时会被具体的类型实例化。
三种使用形式:
1.泛型类:类型参数用于类的定义中,则该类被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:List、Set、Map等。
//基本语法:
class 类名称 <泛型标识> {
private 泛型标识 /*(成员变量类型)*/ 变量名;
.....
}
}
//常见的泛型标识:
T :代表一般的任何类。
E :代表 Element 元素的意思,或者 Exception 异常的意思。
K :代表 Key 的意思。
V :代表 Value 的意思,通常与 K 一起配合使用。
S :代表 Subtype 的意思。
//举例:
public class Generic<T> {
// key 这个成员变量的数据类型为 T, T 的类型由外部传入
private T key;
// 泛型构造方法形参 key 的类型也为 T,T 的类型由外部传入
public Generic(T key) {
this.key = key;
}
// 泛型方法 getKey 的返回值类型为 T,T 的类型由外部指定
public T getKey(){
return key;
}
}
从上述例子可得,在泛型类中,类型参数定义的位置有三处:
1.非静态的成员属性类型
2.非静态方法的形参类型(包括非静态成员方法和构造器)
3.非静态的成员方法的返回值类型
泛型类的使用:在创建泛型类的对象时,必须指定类型参数 T 的具体数据类型,即尖括号 <> 中传入的什么数据类型,T 便会被替换成对应的类型。如果 <> 中什么都不传入,则默认是 < Object >。
假设有如下泛型类:
public class Generic<T> {
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey(){
return key;
}
}
当创建一个 Generic< T > 类对象时,会向尖括号 <> 中传入具体的数据类型。
@ Test
public void test() {
Generic<String> generic = new Generic<>();// 传入 String 类型
// <> 中什么都不传入,等价于 Generic<Object> generic = new Generic<>();
Generic generic = new Generic();
}
2.泛型接口:
//基本语法
public interface 接口名<类型参数> {
...
}
//举例
public interface Inter<T> {
public abstract void show(T t) ;
}
泛型接口中的类型参数,在该接口被继承或者被实现时确定。
(1)定义一个泛型接口如下:
- 注意:在泛型接口中,静态成员也不能使用泛型接口定义的类型参数。
interface IUsb<U, R> {
int n = 10;
U name;// 报错! 接口中的属性默认是静态的,因此不能使用类型参数声明
R get(U u);// 普通方法中,可以使用类型参数
void hi(R r);// 抽象方法中,可以使用类型参数
// 在jdk8 中,可以在接口中使用默认方法, 默认方法可以使用泛型接口的类型参数
default R method(U u) {
return null;
}
}
(2)定义一个接口 IA 继承了 泛型接口 IUsb,在 接口 IA 定义时必须确定泛型接口 IUsb 中的类型参数。
// 在继承泛型接口时,必须确定泛型接口的类型参数
interface IA extends IUsb<String, Double> {
...
}
// 当去实现 IA 接口时,因为 IA 在继承 IUsu 接口时,指定了类型参数 U 为 String,R 为 Double
// 所以在实现 IUsb 接口的方法时,使用 String 替换 U,用 Double 替换 R
class AA implements IA {
@Override
public Double get(String s) {
return null;
}
@Override
public void hi(Double d) {
...
}
}
(3)定义一个类 BB 实现了 泛型接口 IUsb,在 类 BB 定义时需要确定泛型接口 IUsb 中的类型参数。
// 实现接口时,需要指定泛型接口的类型参数
// 给 U 指定 Integer, 给 R 指定了 Float
// 所以,当我们实现 IUsb 方法时,会使用 Integer 替换 U, 使用 Float 替换 R
class BB implements IUsb<Integer, Float> {
@Override
public Float get(Integer integer) {
return null;
}
@Override
public void hi(Float afloat) {
...
}
}
(4)定义一个类 CC 实现了 泛型接口 IUsb 时,若是没有确定泛型接口 IUsb 中的类型参数,则默认为 Object。
// 实现泛型接口时没有确定类型参数,则默认为 Object
// 建议直接写成 IUsb<Object, Object>
class CC implements IUsb {//等价 class CC implements IUsb<Object, Object>
@Override
public Object get(Object o) {
return null;
}
@Override
public void hi(Object o) {
...
}
}
(5)定义一个类 DD 实现了 泛型接口 IUsb 时,若是没有确定泛型接口 IUsb 中的类型参数,也可以将 DD 类也定义为泛型类,其声明的类型参数必须要和接口 IUsb 中的类型参数相同。
// DD 类定义为 泛型类,则不需要确定 接口的类型参数
// 但 DD 类定义的类型参数要和接口中类型参数的一致
class DD<U, R> implements IUsb<U, R> {
...
}
3.泛型方法:-------------------------
通配符:
泛型能够处理某一类型范围内
的类型参数,比如某个泛型类和它的子类,为此 Java 引入了泛型通配符
这个概念。
泛型通配符有 3 种形式:
- <?> :被称作无限定的通配符。
- <? extends T> :被称作有上界的通配符。
- <? super T> :被称作有下界的通配符。
在引入泛型通配符之后,我们便得到了一个在逻辑上
可以表示为某一类型参数范围的父类引用类型。举例来说,泛型通配符可以表示 Pair< Integer > 和 Pair< Number > 两者的父类引用类型
。
1.上界通配符
<? extends T> 的定义
上界通配符 <? extends T>:T 代表了类型参数的上界,<? extends T>表示类型参数的范围是 T 和 T 的子类。需要注意的是: <? extends T> 也是一个数据类型实参,它和 Number、String、Integer 一样都是一种实际的数据类型。
上界通配符表示类型是 T
或 T
的子类。它限制了泛型类型的上限,使得泛型类型必须是指定类型的子类型。常用于只需要读取数据的场景。
作用
- 读取数据:确保读取的数据类型至少是
T
,保证类型安全。 - 协变性:使得泛型能够处理
T
及其子类的集合,增加了泛型方法的灵活性。
public class GenericType {
public static void main(String[] args) {
ArrayList<Number> list01 = new ArrayList<Integer>();// 编译错误
ArrayList<? extends Number> list02 = new ArrayList<Integer>();// 编译正确
}
}
用法:
public class Test {
public static void main(String[] args) {
// 创建一个 ArrayList<Integer> 集合
ArrayList<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
// 将 ArrayList<Integer> 传入 printIntVal() 方法
printIntVal(integerList);
// 创建一个 ArrayList<Float> 集合
ArrayList<Float> floatList = new ArrayList<>();
floatList.add((float) 1.0);
floatList.add((float) 2.0);
// 将 ArrayList<Float> 传入 printIntVal() 方法
printIntVal(floatList);
}
public static void printIntVal(ArrayList<? extends Number> list) {
// 遍历传入的集合,并输出集合中的元素
for (Number number : list) {
System.out.print(number.intValue() + " ");
}
System.out.println();
}
}
2.下界通配符:
下界通配符 <? super T>:T 代表了类型参数的下界,<? super T>表示类型参数的范围是 T 和 T 的超类,直至 Object。需要注意的是: <? super T> 也是一个数据类型实参,它和 Number、String、Integer 一样都是一种实际的数据类型。
ArrayList<? super Integer> 在逻辑上表示为 Integer 类以及 Integer 类的所有父类,它可以代表 ArrayList< Integer>、ArrayList< Number >、 ArrayList< Object >中的某一个集合,但实质上它们之间没有继承关系。
下界通配符表示类型是 T
或 T
的超类。它限制了泛型类型的下限,使得泛型类型必须是指定类型的超类型。常用于需要向集合中添加数据的场景。
- 写入数据:确保向集合中添加的数据类型至少是
T
,保证类型安全。 - 逆变性:使得泛型能够处理
T
及其超类的集合,增加了泛型方法的灵活性。
public class GenericType {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<Number>();// 编译错误
ArrayList<? super Integer> list02 = new ArrayList<Number>();// 编译正确
}
}
用法:
public class Test {
public static void main(String[] args) {
// 创建一个 ArrayList<? super Number> 集合
ArrayList<Number> list = new ArrayList();
// 往集合中添加 Number 类及其子类对象
list.add(new Integer(1));
list.add(new Float(1.1));
// 调用 fillNumList() 方法,传入 ArrayList<Number> 集合
fillNumList(list);
System.out.println(list);
}
public static void fillNumList(ArrayList<? super Number> list) {
list.add(new Integer(0));
list.add(new Float(1.0));
}
}
3.无限定通配符 <?>
?
代表了任何一种数据类型,能代表任何一种数据类型的只有 null。需要注意的是: <?>
也是一个数据类型实参,它和 Number、String、Integer 一样都是一种实际的数据类型。
(1)ArrayList<?> 在逻辑上表示为所有数据类型的父类,它可以代表 ArrayList< Integer>、ArrayList< Number >、ArrayList< Object >中的某一个集合,但实质上它们之间没有继承关系。
public class GenericType {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>(123, 456);
ArrayList<?> list02 = list01; // 安全地向上转型
}
}
(2)ArrayList<?> 既没有上界也没有下界,因此,它可以代表所有数据类型的某一个集合,但我们不能指定 ArrayList<?> 的数据类型。
public class GenericType {
public static void main(String[] args) {
ArrayList<?> list = new ArrayList<>();
list.add(null);// 编译正确
Object obj = list.get(0);// 编译正确
list.add(new Integer(1));// 编译错误
Integer num = list.get(0);// 编译错误
}
}
(3)大多数情况下,可以用类型参数 < T > 代替 <?> 通配符。
上界通配符<?extends T> 和下界通配符<? super T>的区别
-
读取与写入:
- 上界通配符 (
? extends T
):主要用于读取数据,不能写入数据(除了null
)。 - 下界通配符 (
? super T
):主要用于写入数据,读取数据时只能读取为Object
类型。
- 上界通配符 (
<? extends T> 允许调用读方法T get()获取 T 的引用,但不允许调用写方法 set(T)传入 T 的引用(传入 null 除外)。
<? super T> 允许调用写方法set(T)传入 T 的引用,但不允许调用读方法 T get()获取 T 的引用(获取 Object 除外)。
-
适用场景:
- 上界通配符:适用于对集合进行只读操作的场景,如计算总和、遍历等。编译器将只允许读操作,不允许写操作。即只可以取值,不可以设值。
- 下界通配符:适用于对集合进行写操作的场景,如添加元素。编译器将只允许写操作,不允许读操作。即只可以设值(比如 set 操作),不可以取值(比如 get 操作)。
-
协变与逆变:
- 上界通配符:协变性,允许泛型处理
T
及其子类。 - 下界通配符:逆变性,允许泛型处理
T
及其超类。
- 上界通配符:协变性,允许泛型处理
-
类型安全:
- 上界通配符:在读取时保证类型安全,因为只能读取
T
或T
的子类。 - 下界通配符:在写入时保证类型安全,因为只能写入
T
或T
的子类。
- 上界通配符:在读取时保证类型安全,因为只能读取
超类:= 父类 = 基类
参考:Java——重写(Override)与重载(Overload)(概念理解+应用举例)_java重写是什么意思-CSDN博客
重载:
同一个方法根据输入数据的不同,做出不同的处理
class Overloading {
public int test() {
System.out.println("test1");
return 1;
}
public void test(int a) {
System.out.println("test2");
}
//以下两个方法中参数类型的顺序不同
public String test(int a,String s) {
System.out.println("test3");
return "test方法被重载第二次";
}
public String test(String s,int a) {
System.out.println("test4");
return "test方法被重载第三次";
}
}
public class Overload {
public static void main(String[] args) {
Overloading a=new Overloading();
System.out.println(a.test());
a.test(1);
System.out.println(a.test(1,"test3"));
System.out.println(a.test("test4",1));
}
}
重写:
当子类继承父类相同的方法时,输入数据一样,但要做出有别于父类的响应时,要覆盖父类的方法
class AnimalPark {
public void move() {
System.out.println("动物可以移动!");
}
}
class Dogs extends AnimalPark {
public void move() {
System.out.println("狗可以跑和跳!");
}
}
public class Override {
public static void main(String[] args) {
AnimalPark a=new AnimalPark(); //
AnimalPark b=new Dogs(); //
a.move();
b.move();
}
}
标签:Java,ArrayList,通配符,接口,类型,base,泛型,public
From: https://blog.csdn.net/m0_54463709/article/details/139294873