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

做的网站浏览器提示不安全问题陕西优化疫情防控措施

做的网站浏览器提示不安全问题,陕西优化疫情防控措施,福田小货车,时时彩 网站建设目录 一. 什么是泛型 二. 引出泛型 三. 泛型语法 四. 泛型的使用 五. 泛型是如何编译的 5.1 擦除机制 六. 泛型的继承 6.1 泛型类继承非泛型类 6.2 泛型类继承泛型类 6.2.1 父类的同名传递 6.2 2 父类的异名传递 6.2.3 父类固定类型传递 6.2.4 子类添加参数 七. 泛…

目录

一. 什么是泛型

二. 引出泛型

三. 泛型语法

四. 泛型的使用

五. 泛型是如何编译的

5.1 擦除机制

六. 泛型的继承

6.1 泛型类继承非泛型类

6.2 泛型类继承泛型类

6.2.1 父类的同名传递

6.2 2 父类的异名传递

6.2.3 父类固定类型传递

6.2.4 子类添加参数

七. 泛型的上界

7.1语法

7.2 示例

7.2.1 普通示例

7.2.2 复杂示例

八. 泛型方法

8.1 语法

8.2 非泛型类中的泛型方法

8.3 泛型类中的泛型方法

九. 通配符

9.1 通配符的上界

9.2 通配符的下界

9.3 通配符的限制


一. 什么是泛型

泛型是一种在编程语言中允许代码在定义时使用参数化类型的特性,它使得代码可以处理不同类型的数据,同时保持类型安全,提高代码的复用性和可维护性,比如在Java中可以通过泛型定义一个能存储任意类型数据的集合类。

二. 引出泛型

class MyArray{public Object[] arr=new Object[10];public Object getPos(int pos) {return arr[pos];}public void setArr(Object value,int pos){this.arr[pos]=value;}
}public class Test {public static void main(String[] args) {MyArray array =new MyArray();array.setArr(10,0);//父类的对象赋值给子类时,必须要强转Integer j=(Integer)array.getPos(0);System.out.println(j);}}

这样每次取出的值都要进行强制类型转化,不灵活,所以我们需要一个机制能帮助我们使得代码更灵活

三. 泛型语法

class 泛型类名称 < T >{

}

class 泛型类名称 < T ,E,K ....>{

}

注意:

  • 这里的T相当于是个占位符 ,表示当前类是一个泛型类
  • T也可与是其他的字母

四. 泛型的使用

注意:

  • < >中传入的类型必须是引用/自定义数据类型,不能是基本数据类型
  • 在实例化泛型类时,后面< >中可以不写(会发生类型推导)
  • 泛型类还可以继承,下面会讲到
  • 泛型的优点:数据类型参数化,编译时自动进行类型检查和转化

五. 泛型是如何编译的

5.1 擦除机制

泛型擦除是指在编译阶段,编译器会将泛型类型信息擦除,把泛型参数替换为其限定类型(通常是 Object 类型,如果有指定上限则替换为上限类型),并且在必要的地方插入类型转换以保持类型安全,还可以生成桥接方法以保持多态性,使得运行时的字节码中不再包含泛型的类型信息。

擦除前

public class MyArray <T>{public Object[] array=new Object[10];public void setArray(int pose,T value) {this.array[pose] = value;}public T getArray(int pos) {return (T)this.array[pos];}
}

擦除后

public class MyArray{public Object[] array=new Object[10];public void setArray(int pose,Object value) {this.array[pose] = value;}public Object getArray(int pos) {return this.array[pos];}
}

补充:为什么array数组不能写成泛型数组?

答:数组创建规则:在Java中,数组的创建必须使用具体的类型,例如 int[ ] ,String[ ]等,你不能使用泛型类型T[ ] 直接创建数组,因为编译器不知道 T 具体是什么类型,且因为泛型的擦除机制是在编译时发生的,运行时是没有泛型这个概念的

六. 泛型的继承

6.1 泛型类继承非泛型类

class A {public int i;public int getI() {return i;}
}public class B<T> extends A{public Object[] arr=new Object[10];public void func (int pos,T value){this.arr[pos] =value;}@Overridepublic int getI() {return super.getI();}
}

泛型类继承非泛型类时,重写父类的方法时,父类的方法签名不会改变,也不能将它改为泛型方法

6.2 泛型类继承泛型类

6.2.1 父类的同名传递

class A<T>{public T i;public T getI() {return i;}
}
public class B<T> extends A<T>{public Object[] arr=new Object[10];public void func (int pos,T value){this.arr[pos] =value;}@Overridepublic T getI() {return super.getI();}
}

6.2 2 父类的异名传递

class A<U>{public U i;public U getI() {return i;}
}
public class B<T> extends A<T>{public Object[] arr=new Object[10];public void func (int pos,T value){this.arr[pos] =value;}@Overridepublic T getI() {return super.getI();}
}

这里不是修改父类的定义,而是指定类型参数的对应关系,不影响父类的原始定义,只是子类使用时的类型绑定方式,并且编译后会被类型消除,运行时没有区别(编译器理解U)

6.2.3 父类固定类型传递

class A<U>{public U i;public U getI() {return i;}
}
public class B<T> extends A<String>{public Object[] arr=new Object[10];public void func (int pos,T value){this.arr[pos] =value;}@Overridepublic String getI() {return super.getI();}
}
//编译时生成的桥接方法public Object getI() {getI();}

这是实际上是泛型的桥接方法(为什么重写父类后的方法签名不一致却也能构成重写),下面是关于桥接方法的具体介绍:

在子类重写泛型父类的方法时,尽管在源代码中可以明确地指定重写方法的返回类型为具体的类型参数(如 SubGenericClass 中 getValue 方法返回 Integer ),但由于类型擦除,在字节码层面父类的方法签名会变为返回 Object 类型。为了保证多态性,即根据对象的实际类型来正确调用重写后的方法,就需要桥接方法来进行中间转换。
 
桥接方法的工作方式
 
编译器会在子类中生成桥接方法,其方法签名与父类被擦除后的方法签名一致(返回类型为擦除后的类型)。在桥接方法内部,会调用子类中实际重写的方法。如前面例子中, SubGenericClass 的桥接方法 public Object getValue() 会调用子类真正的 public Integer getValue() 方法,这样在运行时,无论通过父类引用还是子类引用调用 getValue 方法,都能正确地根据对象的实际类型来执行子类重写后的方法,实现多态性

6.2.4 子类添加参数

class A<U>{public U i;public U getI() {return i;}
}
public class B<T,K> extends A<T>{public K m;public Object[] arr=new Object[10];public void func (int pos,T value){this.arr[pos] =value;}public K func2(){return m;}@Overridepublic T getI() {return super.getI();}
}

总结:

  • 在泛型子类继承泛型父类在签名时,父类的泛型参数要与子类泛型参数的其中一个参数名相同(子类必须为父类的每个参数提供类型),也可以给父类指定具体类型
  • 在Java中,会根据子类的参数传递给父类参数,在继承的关系中父类参数的具体类型由子类决定

七. 泛型的上界

泛型的上界是在定义泛型类型时,对泛型参数的类型进行限制,指定其必须是某个类或接口的子类或实现类。

7.1语法

class 泛型类名称 <类型形参 extends 类型边界>{

          ......
}

7.2 示例

7.2.1 普通示例

7.2.2 复杂示例

类型边界也可以是接口,表示只有实现了该接口的类型才能传入该参数

class 泛型类名称 <类型形参 extends 接口>{

          ......
}

小测试:写一个泛型类,在其中定义一个方法来求任意类型数组的最大值

public class A <T extends Comparable<T>>{public T Max(T[] arr){T max=arr[0];for (int i = 0; i < arr.length; i++) {if(arr[i].compareTo(max)>0){max=arr[i];}}return max;}}class test {public static void main(String[] args) {Integer[] arr=new Integer[]{1,24,26,75,35,56};A<Integer> a=new A<>();Integer m=a.Max(arr);System.out.println(m);}
}

注意:

  • 传入的类型必须是类型边界的子类或者类型边界本身,如果extends后面是接口的话,传入的参数类型必须是实现了该接口的类
  • 如果没有指定类型边界则默认为object类
  • 泛型没有下界

八. 泛型方法

泛型方法是Java中一种允许在方法中使用泛型类型参数的特性。它可以使方法更具通用性,能够处理不同类型的数据,而不需要为每种数据类型都编写重复的代码。

8.1 语法

方法限定符 <类型形参列表> 返回值类型方法名称(形参列表) {

...

}

8.2 非泛型类中的泛型方法

public class A {public <T> T func(T i){return i;}public static <T> T func(){return null;}public static void main(String[] args) {A a=new A();Integer i=10;Integer b= a.func(i);//类型推导Integer c= a.<Integer>func(i);//非类型推导Integer m=A.<Integer>func();//非类型推导}
}

注意:

  • 泛型方法会根据你传入的参数来进行类型推导,推导出第一个<T>中的类型形参
  • 如果是无参数的泛型方法就必须要在调用时显式指定类型

8.3 泛型类中的泛型方法

class GenericClass<T> {private T data;public GenericClass(T data) {this.data = data;}// 泛型方法也定义了T作为类型参数,这里会隐藏类的Tpublic <T> void printType(T item) {System.out.println("方法中的T类型: " + item.getClass().getName());// 这里的data是类的成员变量,类型是类定义的TSystem.out.println("类中的T类型: " + data.getClass().getName());}
}public class Main {public static void main(String[] args) {GenericClass<Integer> generic = new GenericClass<>(10);generic.printType("Hello");}
}

注意:

  • 当泛型类的参数类型名与泛型方法名一致时,泛型方法会隐藏泛型类的参数类型,即泛型方法中的T是在调用方法时传入的类型参数,而不是泛型类的参数类型
  • 为了避免混淆,泛型方法的参数类型名尽量与泛型类的参数类型名不同

九. 通配符

在Java泛型中,通配符 ?是一种用于表示不确定类型的特殊语法,它使得泛型代码更加灵活和通用

9.1 通配符的上界

<? extends 上界>

传入的数据类型必须是上界本身或者上界的子类

import java.util.ArrayList;
import java.util.List;class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}public class UpperBoundWildcardExample {public static double calculateTotalWeight(List<? extends Animal> animals) {double totalWeight = 0.0;// 假设每个动物都有weight属性,这里简单模拟for (Animal animal : animals) {// 可以安全地读取Animal及其子类对象,因为上界是AnimaltotalWeight += 1.0; }return totalWeight;}public static void main(String[] args) {List<Cat> catList = new ArrayList<>();catList.add(new Cat());List<Dog> dogList = new ArrayList<>();dogList.add(new Dog());double catTotalWeight = calculateTotalWeight(catList);double dogTotalWeight = calculateTotalWeight(dogList);System.out.println("猫的总重量: " + catTotalWeight);System.out.println("狗的总重量: " + dogTotalWeight);}
}

注意:使用了通配符的上界,就只能读取数据,不能写入数据,因为我们不能保证传入的是那种参数类型(是上界本身还是上界的子类是不确定的),只要使用了?,编译器在编译时的定义是模糊的(即使传入的是具体的参数类型)

9.2 通配符的下界

<? super 下界>

传入的数据类型必须是上界本身或者上界的父类

import java.util.ArrayList;
import java.util.List;class Fruit {}
class Apple extends Fruit {}
class RedApple extends Apple {}public class LowerBoundWildcardExample {public static void addApple(List<? super Apple> fruitList) {Apple apple = new Apple();// 可以安全地添加Apple及其子类对象到列表中fruitList.add(apple); RedApple redApple = new RedApple();fruitList.add(redApple); }public static void main(String[] args) {List<Apple> appleList = new ArrayList<>();List<Fruit> fruitList = new ArrayList<>();addApple(appleList);addApple(fruitList);System.out.println("苹果列表: " + appleList);System.out.println("水果列表: " + fruitList);}
}

注意:使用了通配符的上界,就只能写入数据,不能读取数据,但是写入数据只能写入下界的子类对象,因为我们不能保证传入的是那种参数类型

9.3 通配符的限制

  • 不能用于定义泛型类或方法:

   通配符只能在方法的参数、局部变量或表达式中使用,不能用于定义泛型类、泛型接口或泛型方法的类型参数。例如, class MyClass<?> 是不合法的定义。

  • 不能直接实例化通配符类型:
List<?> list = new ArrayList<?>();  // 编译错误
List<? extends Number> numbers = new ArrayList<? extends Number>(); // 编译错误List<?> list = new ArrayList<String>();  // 合法
List<? extends Number> numbers = new ArrayList<Integer>(); // 合法
  • 方法调用限制:

 只是可以调用与元素类型无关的通用方法

List<?> list = new ArrayList<String>();// ✅ 可以调用的方法(不依赖元素类型):list.size();      // 获取大小list.isEmpty();   // 判断空list.clear();     // 清空集合Iterator<?> it = list.iterator(); // 获取迭代器// ❌ 不能调用的方法(依赖元素类型):list.add("hello");       // 编译错误list.add(new Object());  // 编译错误list.remove("hello");    // 编译错误(但实际可以调用,特殊例外)
  • 类型引用限制:

不能直接引用通配符类型,?只能存在于<>中

class MyClass<?> { ... }  // 编译错误
? myVariable;  // 编译错误
  • 数组创建限制:
List<?>[] array = new List<?>[10];  // 编译错误

http://www.dtcms.com/wzjs/2100.html

相关文章:

  • 互联网招聘网站排名国外媒体报道
  • icp备案查询网站淘宝付费推广有几种方式
  • 霞浦县网站seo优化排名搜索引擎的优化方法有哪些
  • 建筑施工企业中是应急救援领导关键词优化武汉
  • ipsw 是谁做的网站百度霸屏推广多少钱一个月
  • 学做淘宝客网站百度公司推广电话
  • 网站建设实验作业抖音seo是什么
  • 宁波建筑公司排名上海网站seo招聘
  • BC网站推广怎么做seo网络优化专员
  • ps做网站时画布宽度杭州网站推广优化
  • 博士后是否可以做网站负责人百家号权重查询站长工具
  • 工信部域名查询免费刷seo
  • 渝水区城乡建设局网站bt樱桃 磁力岛
  • 可以做网站的魔盒镇江seo快速排名
  • wordpress not found梅州seo
  • 江苏优质网站制作公司市场营销案例分析
  • 购买 做网站 客户注册平台
  • 医院网站建设联系方式无锡百度快速优化排名
  • 布吉做棋牌网站建设哪家技术好广州最新疫情通报
  • 电脑网站转手机版石家庄热搜
  • 网站不用域名可以吗seo站长优化工具
  • 中石油技术开发公司网站六六seo基础运营第三讲
  • 做网站客户要求分期软文编辑器
  • wordpress添加ga代码可靠的网站优化
  • 手机wap版网站制作网络推广好做吗?
  • 门户网站建设管理工作的意见福州seo建站
  • 拓者吧室内设计seo软件工具箱
  • 我做中医培训去哪个网站找学员适合发朋友圈的营销广告
  • 廊坊市网站建设百度指数在线查询前100
  • 重庆建设银行网站百度网站推广价格