1.反射,泛型

1.2.1 反射机制

Java的反射机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。

1.2.2 内置Class实例和数组的生命周期

Class的生命周期:

http://t.csdnimg.cn/TsmMa

数组的生命周期:
1.创建阶段:当程序中创建一个数组时,JVM会在堆内存中分配一块连续的内存空间来存储数组元素,并将数组的引用存放在栈内存中。
2使用阶段:在程序运行过程中,可以通过数组的引用来访问和操作数组元素,包括读取和修改元素的值。
3回收阶段:当数组不再被引用时,JVM会通过垃圾回收器来自动回收数组所占用的内存空间,释放资源。

1.2.3 反射与设计模式结合

1.工厂模式(Factory Pattern): 工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。Java反射可以动态地创建对象,因此可以与工厂模式结合使用,实现更加灵活的对象创建。

// 定义一个接口
public interface Shape {void draw();
}// 定义具体的实现类
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing Circle");}
}public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Drawing Rectangle");}
}// 定义工厂类
public class ShapeFactory {public static Shape createShape(String shapeType) {try {Class<?> clazz = Class.forName(shapeType);return (Shape) clazz.getDeclaredConstructor().newInstance();} catch (Exception e) {e.printStackTrace();}return null;}
}// 使用工厂类创建对象
public class FactoryPatternExample {public static void main(String[] args) {Shape circle = ShapeFactory.createShape("com.example.Circle");circle.draw();Shape rectangle = ShapeFactory.createShape("com.example.Rectangle");rectangle.draw();}
}

2.单例模式(Singleton Pattern): 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。通过Java反射,可以破坏单例模式的封装性,因此在使用反射时需要特别注意单例模式的实现。

// 单例类
public class Singleton {private static Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}// 使用反射获取单例对象
public class SingletonReflectionExample {public static void main(String[] args) {Singleton instance1 = Singleton.getInstance();try {Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();constructor.setAccessible(true);Singleton instance2 = constructor.newInstance();System.out.println(instance1 == instance2); // 输出false,破坏了单例模式} catch (Exception e) {e.printStackTrace();}}
}

3.代理模式(Proxy Pattern): 代理模式是一种结构型设计模式,它允许通过代理类来控制对目标对象的访问。Java反射可以动态地创建代理对象,从而与代理模式结合使用。

// 定义接口
public interface Image {void display();
}// 定义真实对象
public class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadFromDisk();}@Overridepublic void display() {System.out.println("Displaying " + filename);}private void loadFromDisk() {System.out.println("Loading " + filename + " from disk");}
}// 定义代理类
public class ImageProxy implements Image {private String filename;private RealImage realImage;public ImageProxy(String filename) {this.filename = filename;}@Overridepublic void display() {if (realImage == null) {realImage = new RealImage(filename);}realImage.display();}
}// 使用代理类
public class ProxyPatternExample {public static void main(String[] args) {Image image = new ImageProxy("test.jpg");image.display();}
}

4策略模式(Strategy Pattern): 策略模式是一种行为型设计模式,它定义了一系列算法,将每个算法封装起来,并使它们可以相互替换。Java反射可以动态地选择和应用不同的策略,从而与策略模式结合使用。

// 定义策略接口
interface PaymentStrategy {void pay(int amount);
}// 定义具体的策略类
class CreditCardPayment implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using credit card");}
}class PayPalPayment implements PaymentStrategy {@Overridepublic void pay(int amount) {System.out.println("Paid " + amount + " using PayPal");}
}// 定义上下文类
class PaymentContext {private PaymentStrategy strategy;public PaymentContext(PaymentStrategy strategy) {this.strategy = strategy;}public void pay(int amount) {strategy.pay(amount);}
}// 使用策略模式
public class StrategyPatternExample {public static void main(String[] args) {PaymentStrategy creditCardPayment = new CreditCardPayment();PaymentStrategy payPalPayment = new PayPalPayment();PaymentContext context1 = new PaymentContext(creditCardPayment);context1.pay(100);PaymentContext context2 = new PaymentContext(payPalPayment);context2.pay(200);}
}

5观察者模式(Observer Pattern): 观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。Java反射可以动态地注册和通知观察者对象,从而与观察者模式结合使用。

import java.util.ArrayList;
import java.util.List;// 定义观察者接口
interface Observer {void update(String message);
}// 定义主题接口
interface Subject {void registerObserver(Observer observer);void removeObserver(Observer observer);void notifyObservers(String message);
}// 定义具体的主题类
class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();@Overridepublic void registerObserver(Observer observer) {observers.add(observer);}@Overridepublic void removeObserver(Observer observer) {observers.remove(observer);}@Overridepublic void notifyObservers(String message) {for (Observer observer : observers) {observer.update(message);}}
}// 定义具体的观察者类
class ConcreteObserver implements Observer {private String name;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {System.out.println(name + " received message: " + message);}
}// 使用观察者模式
public class ObserverPatternExample {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();ConcreteObserver observer1 = new ConcreteObserver("Observer 1");ConcreteObserver observer2 = new ConcreteObserver("Observer 2");subject.registerObserver(observer1);subject.registerObserver(observer2);subject.notifyObservers("Hello, observers!");}
}

1.3.1 Java自动装箱拆箱

为什么要设计自动装箱和自动拆箱呢?这样设计的好处在于简化了代码编写过程,提高了代码的可读性和易用性。在使用自动装箱和自动拆箱的情况下,可以直接将基本类型和对应的包装类型进行混合使用,而不需要过多地关注类型转换的细节。

另外,自动装箱和自动拆箱也使得泛型和集合类的使用更加便捷。例如,可以直接将基本类型的值放入集合中,而不需要手动进行类型转换。

1.3.2 泛型的使用

泛型(Generics)是一种参数化类型的概念,它允许我们在定义类、接口和方法时使用类型参数,从而使得这些类、接口和方法能够操作各种不同类型的数据,而不需要进行类型转换。泛型的使用可以提高代码的重用性、可读性和类型安全性。

泛型的基本语法包括使用尖括号<>来声明类型参数,通常用大写字母来表示类型参数。例如,表示一个泛型类型参数,可以在类、接口或方法的声明中使用。

下面是一些常见的泛型使用方式:
在类中使用泛型:

public class Box<T> {private T value;public Box(T value) {this.value = value;}public T getValue() {return value;}
}

在接口中使用泛型:

public interface List<T> {void add(T value);T get(int index);
}

在方法中使用泛型:

public <T> T getValue(T[] array, int index) {return array[index];
}

泛型的使用可以提高代码的灵活性和安全性,避免了类型转换的繁琐和可能导致的运行时异常
示例:

public class GenericBoxExample {public static void main(String[] args) {Box<Integer> intBox = new Box<>(10);int value = intBox.getValue();  // 不需要进行类型转换System.out.println(value);Box<String> stringBox = new Box<>("Hello");String str = stringBox.getValue();System.out.println(str);}
}class Box<T> {private T value;public Box(T value) {this.value = value;}public T getValue() {return value;}
}

1.3.3 泛型的类型擦除

泛型是在编译时期进行类型检查的,但在运行时会被擦除。这意味着在运行时,泛型类型信息会被擦除,而只保留原始类型的信息。这种设计是为了向后兼容旧版本的Java,并且使得泛型可以在不同类型之间进行转换。

具体来说,泛型类型信息在编译时会被擦除,而在运行时只能获取到原始类型的信息。例如,对于泛型类List,在运行时只能获取到List,而无法获取到List的信息。

这种类型擦除的设计有以下几个影响和好处:

向后兼容性:类型擦除使得支持泛型的类可以与旧版本的Java代码兼容,因为在运行时泛型信息已经被擦除。
减少重复信息:类型擦除减少了在运行时存储和传递泛型类型信息的开销,从而提高了性能和减少了内存占用。
简化编译后的代码:类型擦除使得编译后的代码更加简洁,因为泛型信息被擦除后,编译器不需要生成额外的类型信息。

举例:

public class GenericTypeErasureExample {public static void main(String[] args) {List<String> stringList = new ArrayList<>();stringList.add("Hello");String value = stringList.get(0);  // 在运行时,只能获取到原始类型List的信息System.out.println(value);}
}

在上面的例子中,尽管在编译时使用了List类型,但在运行时只能获取到List类型的信息。这就是泛型类型擦除的影响之一。需要注意的是,尽管泛型类型信息在运行时被擦除,但是在编译时仍然会进行类型检查,以确保类型安全性。

java泛型详细

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/241210.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JavaEE进阶学习:Spring MVC 程序开发

1.什么是 Spring MVC Spring Web MVC 是基于Servlet API 构建的原始 Web 框架&#xff0c;从一开始就包含在Spring 框架中。它的正式名称 “Spring Web MVC” 来自其源模块的名称(Spring-webmvc)&#xff0c;但它通常被称为“Spring MVC”。 从上述定义我们可以得出两个关键信…

如何改善与 Next Paint (INP) 的交互

但谷歌也会关注访问者到达后你的网站体验有多好。 在过去的几年里&#xff0c;谷歌已经彻底改变了哪些页面体验信号被收集并用作排名因素。 在引入核心网络指标后&#xff0c;谷歌逐渐调整了它们的衡量方式&#xff0c;以便更好地反映真实的用户体验。 然而&#xff0c;随着…

深入了解Pandas的数据类型

大家好&#xff0c;Pandas是一个功能强大的数据处理和分析库&#xff0c;它提供了丰富的数据类型&#xff0c;使得数据操作更加灵活和高效。本文我们将深入了解Pandas的数据类型&#xff0c;包括Series和DataFrame。 1.Series Series是Pandas中最基本的数据类型&#xff0c;它…

Unity中获取时间戳、日期、时间、毫秒、秒以相互转换、自定义格式时间

Unity中获取时间戳、日期、时间、毫秒、秒以相互转换、自定义格式时间 介绍时间戳是什么什么时候用时间戳 获取时间获取当前时间获取时间戳日期转时间戳时间戳转日期将时间戳转换为多久之前星期自定义格式时间 总结 介绍 这里附带一个时间戳和时间转换的网址 时间戳是什么 时…

【Spring实战】01 配置单数据源

文章目录 1. 定义2. 准备3. 打印连接信息4. 实战1&#xff09;创建表2&#xff09;添加数据3&#xff09;查询数据3&#xff09;执行 5. 详细代码总结 在我们常见的应用程序中&#xff0c;与数据库的交互是不可避免的一部分。Spring 提供了简单而强大的数据访问抽象&#xff0c…

九州金榜|家庭教育幼小衔接家长如何做?

孩子从幼儿园升入小学&#xff0c;很多家长会非常忧虑&#xff0c;进入小学便是孩子学校生涯正式开始&#xff0c;这个阶段作为家长会非常焦虑&#xff0c;会考虑孩子能不能适应小学生活&#xff1f;学习跟不跟得上&#xff0c;一般这个时候&#xff0c;大部分家长就会考虑给孩…

数值分析期末复习

第一章 科学计算 误差 解题步骤 先求绝对误差: ∣ x − x ∗ ∣ |x - x^*| ∣x−x∗∣求相对误差限: ∣ x − x ∗ ∣ x ∗ \frac{|x\,\,-\,\,x^*|}{x^*} x∗∣x−x∗∣​求有效数字 ∣ x − x ∗ ∣ 需要小于它自身的半个单位 |x-x^*|\text{需要小于它自身的半个单位} ∣…

Python入门学习篇(六)——for循环while循环

1 for循环 1.1 常规for循环 1.1.1 语法结构 for 变量名 in 可迭代对象:# 遍历对象时执行的代码 else:# 当for循环全部正常运行完(没有报错和执行break)后执行的代码1.1.2 示例代码 print("----->学生检查系统<------") student_lists["张三",&qu…

drools高级语法

前面章节我们已经知道了一套完整的规则文件内容构成如下&#xff1a; 关键字 描述 package 包名&#xff0c;只限于逻辑上的管理&#xff0c;同一个包名下的查询或者函数可以直接调用 import 用于导入类或者静态方法 global 全局变量 function 自定义函数 query 查询…

Win32 Socket 使用

库说明 Win32 进行网络编程需要使用到 ws2_32.lib 库&#xff0c;它是 Windows Sockets 2 (Winsock2) 的库文件&#xff0c;其主要头文件为winsock2.h。如果使用 Windows.h 头文件则默认包含 winsock.h&#xff0c;他会和 winsock2.h 冲突。可以通过在包含 Windows.h 之前定义…

数据压缩(哈夫曼编码)

【问题描述】在数据压缩问题中&#xff0c;需要将数据文件转换成由二进制字符0、1组成的二进制串&#xff0c;称之为编码&#xff0c;已知待压缩的数据中包含若干字母&#xff08;A-Z&#xff09;&#xff0c;为获得更好的空间效率&#xff0c;请设计有效的用于数据压缩的二进制…

MLX vs MPS vs CUDA:苹果新机器学习框架的基准测试

如果你是一个Mac用户和一个深度学习爱好者&#xff0c;你可能希望在某些时候Mac可以处理一些重型模型。苹果刚刚发布了MLX&#xff0c;一个在苹果芯片上高效运行机器学习模型的框架。 最近在PyTorch 1.12中引入MPS后端已经是一个大胆的步骤&#xff0c;但随着MLX的宣布&#x…

在Excel中,如何简单快速地删除重复项,这里提供详细步骤

当你在Microsoft Excel中使用电子表格时&#xff0c;意外地复制了行&#xff0c;或者如果你正在制作其他几个电子表格的合成电子表格&#xff0c;你将遇到需要删除的重复行。这可能是一项非常无脑、重复、耗时的任务&#xff0c;但有几个技巧可以让它变得更简单。 删除重复项 …

Android Canvas画布saveLayer与对应restoreToCount,Kotlin

Android Canvas画布saveLayer与对应restoreToCount&#xff0c;Kotlin private fun mydraw() {val originBmp BitmapFactory.decodeResource(resources, R.mipmap.pic).copy(Bitmap.Config.ARGB_8888, true)val newBmp Bitmap.createBitmap(originBmp.width, originBmp.heigh…

【Win10安装Qt6.3】安装教程_保姆级

前言 Windows系统安装Qt4及Qt5.12之前版本和安装Qt.12之后及Qt6方法是不同的 &#xff1b;因为之前的版本提供的有安装包&#xff0c;直接一路点击Next就Ok了。但Qt5.12版本之后&#xff0c;Qt公司就不再提供安装包了&#xff0c;不论是社区版&#xff0c;专业版等&#xff0c…

并发控制工具类CountDownLatch、CyclicBarrier、Semaphore

并发控制工具类CountDownLatch、CyclicBarrier、Semaphore 1.CountDownLatch 可以使一个或多个线程等待其他线程各自执行完毕后再执行。 CountDownLatch 是多线程控制的一种工具&#xff0c;它被称为 门阀、 计数器或者闭锁。这个工具经常用来用来协调多个线程之间的同步&…

项目从vue2 升级vue3,项目大迁移 ,UI组件库更换

目录 背景描述 开发准备 第一步&#xff1a;升级环境 第二步&#xff1a;划分功能迁移顺序 第三步&#xff1a;详细了解需要迁移的业务页面 第四步&#xff1a;项目的一些配置的准备 详细开发流程 总结/分析&#xff1a; 背景描述 之前的版本&#xff1a;vue 2.6.8 i…

【PHY6222】绑定详解

1.函数详解 bStatus_t GAPBondMgr_SetParameter( uint16 param, uint8 len, void* pValue ) 设置绑定参数。 bStatus_t GAPBondMgr_GetParameter( uint16 param, void* pValue ) 获取绑定参数。 param&#xff1a; GAPBOND_PAIRING_MODE&#xff0c;配对模式&#xff0c;…

【postgres】8、Range 类型

文章目录 8.17 Range 类型8.17.1 内置类型8.17.2 示例8.17.3 开闭区间8.17.4 无穷区间 https://www.postgresql.org/docs/current/rangetypes.html 8.17 Range 类型 Range 类型&#xff0c;可以描述一个数据区间&#xff0c;有明确的子类型&#xff0c;而且子类型应该能被排序…

计算机网络——数据链路层(三)

前言: 前面我们已经对计算机网络的物理层有了一个大概的了解&#xff0c;今天我们学习的是物理层服务的上一层数据链路层&#xff0c;位于物理层和网络层之间。数据链路层在物理层提供的服务的基础上向网络层提供服务&#xff0c;其最基本的服务是将源自物理层来的数据可靠地传…