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

做网站会遇到的问题有没有电脑做兼职的网站

做网站会遇到的问题,有没有电脑做兼职的网站,网站建设的主要工作内容,c 做网站 知乎Java中泛型擦除及桥接方法 泛型擦除无界擦除上界擦除下界擦除 桥接方法演示案例wrong1wrong2wrong3right 原理总结 泛型擦除 ​ 泛型擦除是Java泛型机制的一个特性#xff0c;它意味着**在编译期间#xff0c;所有的泛型信息都会被移除#xff0c;而在运行时#xff0c;所… Java中泛型擦除及桥接方法 泛型擦除无界擦除上界擦除下界擦除 桥接方法演示案例wrong1wrong2wrong3right 原理总结 泛型擦除 ​ 泛型擦除是Java泛型机制的一个特性它意味着**在编译期间所有的泛型信息都会被移除而在运行时所有泛型类型都转换为其边界类型通常是Object或者对于参数化的类型参数是其指定的边界。这是因为Java的泛型是类型安全的但不是类型保留的**。换句话说泛型只在编译时提供类型检查而运行时并不保留这些类型信息。泛型擦除可以分为以下三类 无界擦除 ​ 无界擦除是指没有指定泛型类型的边界通常使用 ? 作为通配符。这意味着方法或变量可以接受任何类型的对象。例如想象你有一个动物观察站它记录任何动物的信息但不关心它们的类型。 public class ObservationStation {public void recordAnyAnimal(Animal? animal) {// 不关心动物的类型只是记录System.out.println(animal);} }Data NoArgsConstructor public class AnimalT {private T attribute; // 使用泛型T来表示动物的一个属性比如名字、年龄等public Animal(T attribute) {this.attribute attribute;} }public class unBoundMain {public static void main(String[] args) {ObservationStation station new ObservationStation();AnimalString animal1 new Animal(Dog);AnimalInteger animal2 new Animal(1);station.recordAnyAnimal(animal1); // 无界擦除因为可以接受任何Animal类型station.recordAnyAnimal(animal2); // 同理} }​ 在运行时recordAnyAnimal 方法的参数类型被擦除为 Animal这意味着它接受任何 Animal 类型的对象而不管具体的 T 是什么类型。编译器在调用方法时会确保传入的参数是 Animal 的实例。 运行结果 上界擦除 ​ 上界擦除指的是在使用泛型时将泛型参数限制为某种类型的子类型或该类型本身。 Data NoArgsConstructor public class AnimalT extends LivingBeing { // 设置上界T必须是LivingBeing或其子类private T attribute; // 使用泛型T来表示动物的一个属性比如名字、年龄等public Animal(T attribute) {this.attribute attribute;} }public class LivingBeing {private Age age; // 假设Age是一个枚举表示生物的年龄阶段public enum Age {PUPPY,ADULT,SENIOR}// 其他属性和方法 }Data public class Dog extends LivingBeing{private Age age; }public class ObservationStation {public void recordAnyAnimal(Animal? extends LivingBeing animal) { // 上界擦除接受任何LivingBeing或其子类的Animal// 不关心动物的类型只是记录System.out.println(animal);} }public class upBoundMain {public static void main(String[] args) {ObservationStation station new ObservationStation();Dog dog new Dog(); // 创建Dog对象dog.setAge(LivingBeing.Age.ADULT); // 设置Dog的年龄AnimalDog animal1 new Animal(dog); // 将Dog放入AnimalDogstation.recordAnyAnimal(animal1); // 正确Dog是LivingBeing的子类} }​ 在这个案例中我引入了一个假设的LivingBeing基类并修改了Animal类的泛型声明AnimalT extends LivingBeing以及ObservationStation类的recordAnyAnimal方法签名private T attribute;Animal(T attribute) 以确保只有LivingBeing或其子类的Animal实例可以被记录。这样就实现了上界擦除效果 运行结果 下界擦除 ​ 下界通配符允许你指定一个类型参数的下界意味着可以接受该类型及其父类型。类型擦除的确会让泛型参数具体类型信息消失但不影响使用下界或上界通配符来表达类型约束 ​ 尽管类型擦除导致泛型类型参数的具体类型信息在运行时不可用但Java依然支持通过下界通配符如? super T来限定泛型参数确保能够接受类型T及其父类型。这并不意味着下界概念在擦除过程中失效而是指定了类型使用的灵活性在编译时得到保障即使实际类型信息在运行时不可获取。 public class LivingBeing { }public class Dog extends LivingBeing {// Dog类的其他属性和方法 }Data NoArgsConstructor public class AnimalT {private T attribute;public Animal(T attribute) {this.attribute attribute;} }public class ObservationStation {public T extends LivingBeing void recordSpecificAnimal(Animal? super T animal, T specificType) {// 这里可以使用specificType来访问animal的attribute因为animal能接收specificType或其父类型System.out.println(Recording specificType with attribute: animal.getAttribute());}public class lowBoundMain {public static void main(String[] args) {ObservationStation station new ObservationStation();Dog dog new Dog();AnimalDog animal1 new Animal(dog);station.recordSpecificAnimal(animal1, dog); // 正确Dog是Anima} }​ Dog类扩展了LivingBeing这样它就可以用于Animal实例。在ObservationStation类的recordSpecificAnimal方法中Dog实例可以作为T传入因为Dog是LivingBeing的子类。Animal可以作为Animal? super T类型的参数传入其中T是LivingBeing或其子类因为Dog是LivingBeing的子类所以Animal满足Animal? super T的约束。 运行结果 public T extends LivingBeing void recordSpecificAnimal(Animal? super T animal, T specificType)对 此处 T extends LivingBeing 的理解 ​ 是Java泛型中的一个类型参数声明它定义了一个名为 T 的类型变量这个变量必须是 LivingBeing 类或其子类的类型。这里的 extends 关键字用来指定类型参数的边界表明 T 只能是 LivingBeing 或者 LivingBeing 的任何子类 对 此处 ? super T 的理解 ​ ? super T 是下界通配符super 关键字在这里表示下界T 是一个类型参数代表一个未知的具体类型。 当你看到 ? super T你可以理解为“任何类型只要它是 T 或 T 的超类型”。这意味着 animal 变量可以接收任何 Animal 实例只要这个实例的类型是 T 或者是 T 的父类。例如如果 T 被实例化为 Dog那么 animal 可以是 AnimalAnimal或者其他任何 Dog 的父类的 Animal 实例。 桥接方法 ​ 桥接方法Bridge Method是Java编译器在泛型类型擦除过程中自动生成的一种特殊方法旨在解决泛型类型擦除后可能导致的多态性问题。具体来说当一个类继承了泛型类或者实现了泛型接口并且重写了其中的方法时如果子类或实现类的方法签名中的类型参数不同于父类或接口中的类型参数编译器就会自动插入一个桥接方法来确保类型兼容性和多态性的正确实现。 桥接方法的特点如下 透明性对于开发者来说桥接方法是不可见的它在源代码中不会显示仅存在于编译后的字节码中。自动生成桥接方法由Java编译器自动生成无需程序员手动编写。方法签名桥接方法的签名与原始方法相同但其返回类型或参数类型是原泛型类型擦除后的类型通常是Object或其父类而实际执行逻辑则委托给擦除类型参数后的具体实现方法。 访问标志桥接方法在字节码层面会被标记为 ACC_BRIDGE 和 ACC_SYNTHETIC表示这是一个桥接方法和编译器生成的方法。 用途主要目的是为了确保在泛型类型擦除后能够正确地调用到子类中重写的泛型方法维持多态行为。 演示案例 公共部分 public class Pig1 extends Animal {public void setValue(String value) {System.out.println(Pig1.setValue called);super.setValue(value);} }public class Pig2 extends AnimalString {Overridepublic void setValue(String value) {System.out.println(Pig2.setValue called);super.setValue(value);} }public class AnimalT {AtomicInteger updateCount new AtomicInteger();private T value;Overridepublic String toString() {return String.format(value: %s updateCount: %d, value, updateCount.get());}public void setValue(T value) {System.out.println(Animal.setValue called);this.value value;updateCount.incrementAndGet();} }wrong1 public static void main(String[] args) {wrong1();}public static void wrong1() {Pig1 pig1 new Pig1();Arrays.stream(pig1.getClass().getMethods()).filter(method - method.getName().equals(setValue)).forEach(method - {try {System.out.println(method);method.invoke(pig1, test);} catch (Exception e) {e.printStackTrace();}});System.out.println(pig1.toString());}运行结果 执行过程 ​ wrong1方法中对于Pig1对象通过反射获取所有公共方法包括继承的方法中名为setValue的方法。由于Pig1重写了父类Animal的setValue方法但没有改变参数类型所以这里会看到两个方法一个是直接从Pig1类中声明的方法另一个是从父类继承而来的方法因为泛型擦除后父类的setValue(T value)变为setValue(Object value)与子类重写的方法签名相同。这里Pig1重写并不是我们规范化的重写 输出解释 ​ 首先调用了子类Pig1的setValue(String value)打印出Pig1.setValue called然后由于继承关系和方法重写规则继续调用了父类的Animal.setValue(Object value)这一步实际上也是对Pig1中重写方法的调用因此再次打印Animal.setValue called。最后updateCount被增加了2次输出为value: test updateCount: 2。 wrong2 public static void main(String[] args) {wrong2();}public static void wrong2() {Pig1 pig1 new Pig1();Arrays.stream(pig1.getClass().getDeclaredMethods()).filter(method - method.getName().equals(setValue)).forEach(method - {try {System.out.println(method);method.invoke(pig1, test);} catch (Exception e) {e.printStackTrace();}});System.out.println(pig1.toString());}运行结果 wrong2的结果及解释 执行过程 ​ 与wrong1不同的是这里仅获取Pig1声明的自身方法不包括继承的因此只找到了一个setValue(String value)方法。 输出解释 ​ 仅调用了一次Pig1.setValue内部虽然调用了super.setValue(value)但因为是在同一个方法体内updateCount只增加了一次所以输出为value: test updateCount: 1。 wrong3 public static void main(String[] args) {wrong3();}public static void wrong3() {Pig2 pig2 new Pig2();Arrays.stream(pig2.getClass().getDeclaredMethods()).filter(method - method.getName().equals(setValue)).forEach(method - {try {System.out.println(method);method.invoke(pig2, test);} catch (Exception e) {e.printStackTrace();}});System.out.println(pig2.toString());}运行结果 执行过程 ​ 对于Pig2它继承自具有泛型参数的Animal且重写了setValue方法。在反射调用时因为泛型擦除父类会产生一个桥接方法setValue(Object)。wrong3试图调用所有声明的方法包括桥接方法所以setValue(String)和桥接方法setValue(Object)都被调用了。 输出解释 ​ 首先调用子类Pig2的setValue(String value)打印Pig2.setValue called然后因为泛型擦除和桥接方法又调用了父类的Animal.setValue(Object)这里也是调用的子类重写的版本再次打印Animal.setValue called。最终updateCount被增加了2次输出为value: test updateCount: 2。 right public static void main(String[] args) {right();}public static void right() {Pig2 pig2 new Pig2();Arrays.stream(pig2.getClass().getDeclaredMethods()).filter(method - method.getName().equals(setValue) !method.isBridge()).findFirst().ifPresent(method - {try {System.out.println(method);method.invoke(pig2, test);} catch (Exception e) {e.printStackTrace();}});System.out.println(pig2.toString());}运行结果 执行过程 ​ 此方法正确地处理了泛型导致的桥接方法问题。它通过检查方法是否为桥接方法!method.isBridge()只调用了实际需要的setValue(String)方法忽略了桥接方法。 输出解释 ​ 只调用了Pig2.setValue(String value)一次内部调用super.setValue(value)也是针对同一个具体类型的方法因此updateCount只增加了一次输出为value: test updateCount: 1。 原理总结 类型擦除Java泛型在编译后会被擦除这意味着像Animal String 在字节码层面等同于Animal Object 导致方法签名可能变得不明确。 桥接方法为了保证泛型擦除后的多态性编译器会为某些泛型方法生成桥接方法这些方法通常指向具体的实现。 反射调用直接通过反射调用可能遇到桥接方法导致意外的行为如多次调用或不期望的类型转换。正确处理泛型和桥接方法对于避免这些问题至关重要。 本次 Java中常见错误-泛型擦除及桥接方法问题及解决方案 文章到此结束创作不易望我佬们三连支持一下
http://www.tj-hxxt.cn/news/225676.html

相关文章:

  • 企业网站建设湖南岚鸿易企秀h5页面怎么制作
  • 东莞网站营销公司美容类 营销型网站
  • 青岛开发区网站建设哪家好字体中国设计网
  • 网站首页代码红安建设局投诉网站
  • 教做家常菜的视频网站淄博网站快照优化公司
  • 成都网页设计与网站建设成都企业品牌网站建设
  • 校园网站建设促进教学沧州营销软件
  • 最贵网站建设网页制作的目的和意义
  • 做美食介绍的网站员工管理网站模板
  • 网站对图片优化门户网站建站多少钱
  • 重庆专业建网站wordpress修改 id
  • 网站 注册模块怎么做正规网站备案信息表
  • 扬州外贸网站建设wordpress 古风主题
  • 网站建设论文答辩自述网站开发需要兼容到ie几
  • 展厅设计制作网站如何是网站排名上升
  • 化州网站建设公司网站推广策划书目录
  • 怎么查网站是谁建的30天网站建设实录 pdf
  • 网站建设主动型电话销售话术一个网站两个空间
  • 门户网站系统有哪些平台玉溪做网站
  • 海外营销网站建设中天建设集团有限公司第九建设公司
  • 如何攻克房地产网站西地那非最佳吃法
  • 商务局网站建设方案酒店网站html
  • 网站js下载网站建设 推广信息
  • 怎么在网站文本框内做超连接做食品研发都有哪些网站
  • 上海安全建设协会网站freenom申请域名
  • 个人网站域名取名辽宁省工程造价网
  • 潍坊淘宝网站建设google seo怎么优化
  • 做旅游攻略比较好的网站wordpress淘客优惠券
  • 注册网站用什么邮箱广州做网站开发
  • 小型手机网站建设如何优化关键词搜索排名