Java面向对象高级
文章目录
- 面向对象高级
- Object类的常用方法
- 常用方法一(面向对象阶段)
- **== 和 equals 的区别**
- 关键字native
- **单例设计模式(Singleton)**
- 前情回顾(学习基础)静态修饰符Static
- 设计模式概念
- 开发步骤
- **两种实现方式**
- **饿汉式**
- **懒汉式**
- **单例设计模式的线程安全问题**
- main方法
- 分析public static void main(String[] args)
- 命令行参数以及IDEA如何设置使用终端运行
- 实例变量赋值顺序
- **总结···类的加载顺序**
- 分析
- 关键字final
- 关键字final的意义
- **关键字 `final` 用于声明不可变的实体,包括类、方法和变量。**
- `final` 关键字的使用场景
- 关键字abstract(抽象类或抽象方法)
- **关键字 `abstract` 用于声明抽象类和抽象方法**
- 模板设计模式
- 概念
- 细节分析
- 关键字interface(接口)
- **`interface`关键字的详细信息**
- **接口(interface)和抽象类(abstract class)**
- 枚举类
- 内部类
- 四种类型
- Annotation(注解)和元注解
- JUnit单元测试(@Test)
- 包装类
- 用途
- 介绍
- 包装类和基本数据类型之间的转换
- **注意事项**
- 包装类缓存优化:Java中常用数据的缓存技术
- ***包装类与基本数据类型的比较大小***
面向对象高级
Object类的常用方法
常用方法一(面向对象阶段)
clone()
方法:clone()
方法用于创建并返回当前对象的一个副本(克隆)。要使用该方法,类必须实现Cloneable
接口,并重写clone()
方法。Cloneable
接口是一个标记接口,它没有任何方法,只是用于标识该类可以被克隆。- 在实现类中重写
clone()
方法时,通常需要调用super.clone()
方法来获得对象的浅拷贝副本,然后根据需要进行深拷贝。 - 默认情况下,
clone()
方法执行的是浅拷贝,即复制对象的字段值,但不复制引用对象本身。如果需要实现深拷贝,需要在clone()
方法中对引用对象进行单独的拷贝操作。
finalize()
方法:finalize()
方法是垃圾回收器在销毁对象之前调用的方法。- 垃圾回收器(Garbage Collector)负责回收不再使用的对象,但在回收对象之前,会调用对象的
finalize()
方法进行一些清理操作。 - 默认实现的
finalize()
方法为空,但可以在子类中重写该方法,以定义对象在被销毁之前的清理行为,如关闭文件、释放资源等。 - 注意,由于垃圾回收的时机不确定,无法保证
finalize()
方法的及时执行,因此不应该过于依赖该方法来释放资源,而应该使用显式的资源释放方法(如close()
)来确保资源的及时释放。
toString()
方法:toString()
方法返回表示对象的字符串表示。- 在打印对象时,通常会自动调用该方法来获取对象的字符串表示,并输出到控制台。
- 默认实现返回一个由类名、
@
符号和对象的哈希码组成的字符串。 - 可以在类中重写
toString()
方法,以返回更有意义的对象描述。通常,重写的toString()
方法会返回对象的属性值以及其他有用信息的字符串表示。
equals()
方法:equals()
方法用于比较两个对象是否相等。- 默认情况下,
equals()
方法比较的是对象的引用是否相等,即两个对象是否指向同一个内存地址。 - 通过重写
equals()
方法,可以改变相等的定义。通常,重写的equals()
方法会比较对象的属性值,判断它们是否相等。 - 在重写
equals()
方法时,通常还需要重写hashCode()
方法,以保证在使用基于哈希的集合类(如HashMap
、HashSet
)时能够正确地比较和存储对象。- 重写
equals()
方法原则 - 对称性(Symmetry): 如果
x.equals(y)
返回true
,那么y.equals(x)
也应该返回true
。 - 自反性(Reflexivity):
x.equals(x)
必须返回true
。 - 传递性(Transitivity): 如果
x.equals(y)
返回true
,且y.equals(z)
返回true
,那么z.equals(x)
也应该返回true
。 - 一致性(Consistency): 如果
x.equals(y)
返回true
,只要x
和y
的内容不变,无论重复多少次调用x.equals(y)
,都应该返回true
。 - 非空性(Non-nullity):
x.equals(null)
应该始终返回false
。 - 类型检查(Type check):
x.equals(obj)
中,如果obj
的类型与x
不同,应该始终返回false
。
- 重写
== 和 equals 的区别
==
运算符既可以用于比较基本类型的值,也可以用于比较引用类型的内存地址。对于基本类型,它比较的是值是否相等;对于引用类型,它比较的是引用是否指向同一个对象(即内存地址是否相等)。equals()
方法是java.lang.Object
类中定义的方法,如果没有在自定义类中重写该方法,那么默认的行为就是使用==
运算符进行引用相等性的比较。然而,许多类(如String
)会重写equals()
方法,以便根据对象的值来确定相等性,而不仅仅是引用的比较。这可能导致一些误解,使人误认为equals()
方法在所有情况下都比较值。- 在自定义类中,如果需要比较对象的相等性,通常需要重写
equals()
方法,并根据类的属性来确定相等性。这样可以根据具体需求定义对象相等的条件
区别点 | == | equals |
---|---|---|
定义 | == 是一个操作符,用于比较两个变量的值是否相等 | equals 是一个方法,用于比较两个对象的内容是否相等 |
适用类型 | 适用于基本数据类型和对象引用。 | 适用于对象 |
比较方式 | 比较操作数的值 | 比较操作数所引用的对象的内容 |
返回值 | true 如果两个操作数的值相等,否则返回 false | true 如果两个对象的内容相等,否则返回 false |
重载 | == 不能被重载 | equals 方法可以被重载 |
需要根据具体情况选择使用哪种比较方式。
- 对于基本类型,优先使用
==
。 - 对于对象,优先使用
equals()
,除非只想检查是否引用同一个对象,然后才使用==
。
主要差别在于:
==
只检查值。equals()
检查值和类型。
所以总的来说:
- 使用
==
时要小心底层对象可能改变(如String
包装类Integer、
Double等)。 - 优先使用
equals()
来判断对象的相等性。
关键字native
Java中的’ native '关键字用于表示方法是本机函数,这意味着该方法是用Java以外的语言实现的,例如C/ c++,并被编译成Java调用的DLL(动态链接库)。
下面是一些需要理解的关于原生方法的要点:
-
本机方法具有用不同的编程语言(通常是C或c++)实现的主体。然而,由于本机方法体的源代码不对我们开放,我们无法看到它的实现。
-
在Java中定义本机方法时,只声明其签名而不提供实现。
为什么使用本机方法?
虽然Java使用起来很方便,但是有些任务在Java中不容易完成,或者性能很关键。在这种情况下,可以使用本机方法,特别是在与低级操作系统或特定硬件交互时。本机方法提供了一个简洁的接口来执行这些任务,而不必深入研究Java领域之外的复杂细节。
本机方法可以像任何其他Java方法一样被调用者使用
本机方法的存在不会影响调用这些方法的其他类。实际上,调用这些方法的其他类甚至可能不知道它们正在调用本机方法。JVM处理调用本机方法的所有细节。
总之,Java中的本机方法提供了一种方法,可以将用其他语言实现的功能合并到Java程序中,从而实现与低级操作或特定于硬件的任务的有效交互,同时为应用程序的其余部分保持Java语言的便利性和简单性。
单例设计模式(Singleton)
前情回顾(学习基础)静态修饰符Static
设计模式概念
设计模式是在大量的实践中总结
和理论化
之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式免去我们自己再思考和摸索。就像是经典的棋谱,不同的棋局,我们用不同的棋谱。“套路”
经典的设计模式共有23种。每个设计模式均是特定环境下特定问题的处理方法。
简单工厂模式并不是23中经典模式的一种,是其中工厂方法模式的简化版
开发步骤
单例设计模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
在单例模式中,类的构造函数是私有的,这样外部无法直接实例化该类。而通过一个静态方法或静态变量,类提供了对唯一实例的访问。
单例模式的主要特点包括:
- 私有构造函数:将类的构造器的访问权限设置为私有(private),这样外部无法通过构造函数直接创建类的实例。
- 静态实例变量:在类内部创建一个私有静态实例变量,用于保存唯一的实例。
- 提供一个公共的静态访问方法,例如
getInstance()
,用于获取单例实例。在该方法内部进行逻辑判断,如果实例变量为空,则创建一个新的实例并赋值给实例变量。随后的调用都直接返回已创建的实例。
两种实现方式
饿汉式
- 特点:
立即加载
,即在使用类的时候已经将对象创建完毕。 - 优点:实现起来
简单
;没有多线程安全问题。 - 缺点:当类被加载的时候,会初始化static的实例,静态变量被创建并分配内存空间,从这以后,这个static的实例便一直占着这块内存,直到类被卸载时,静态变量被摧毁,并释放所占有的内存。因此在某些特定条件下会
耗费内存
。
class Singleton {// 1.私有化构造器private Singleton() {}// 2.内部提供一个当前类的实例// 4.此实例也必须静态化private static Singleton single = new Singleton();// 3.提供公共的静态的方法,返回当前类的对象public static Singleton getInstance() {return single;}
}
懒汉式
- 特点:
延迟加载
,即在调用静态方法时实例才被创建。 - 优点:实现起来比较简单;当类被加载的时候,static的实例未被创建并分配内存空间,当静态方法第一次被调用时,初始化实例变量,并分配内存,因此在某些特定条件下会
节约内存
。 - 缺点:在多线程环境中,这种实现方法是完全错误的,
线程不安全
,根本不能保证单例的唯一性。- 说明:在多线程章节,会将懒汉式改造成线程安全的模式。
class Singleton {// 1.私有化构造器private Singleton() {}// 2.内部提供一个当前类的实例// 4.此实例也必须静态化private static Singleton single;// 3.提供公共的静态的方法,返回当前类的对象public static Singleton getInstance() {if(single == null) {single = new Singleton();}return single;}
}
单例设计模式的线程安全问题
(先看完线程同步,在回过头看这个内容)
单例设计模式在多线程环境下可能存在线程安全问题,特别是懒汉式单例模式。为了解决线程安全问题,可以使用synchronized
关键字、双重检查锁定、静态内部类等机制来确保只有一个实例被创建,并提供线程安全的访问方式。
- 懒汉式单例模式:
- 懒汉式单例模式指的是在首次使用时才创建实例。当多个线程同时调用获取实例的方法时,可能会导致创建多个实例的问题。
- 若不考虑线程安全,可能出现以下情况:
- 线程A进入获取实例的方法,发现实例为空,创建一个实例。
- 线程B也进入获取实例的方法,此时实例仍为空,线程B也创建一个实例。
- 最终导致多个线程创建了多个实例,违背了单例模式的原则。
- 解决线程安全问题的方法包括:
- 在获取实例的方法上添加
synchronized
关键字,使用同步锁保证只有一个线程能够进入临界区,但会降低性能。 - 使用双重检查锁定(Double-Checked Locking)机制,即在同步块内再进行一次实例是否为空的检查,这样可以避免每次都进入同步块。
- 在获取实例的方法上添加
- 饿汉式单例模式:
- 饿汉式单例模式指的是在类加载时就创建实例。由于实例在类加载时就已经创建,因此不存在并发创建多个实例的问题。
- 饿汉式单例模式是线程安全的,但可能存在性能问题,因为实例在类加载时就创建,无论是否使用都会占用内存。
- 双重检查锁定(Double-Checked Locking):
- 双重检查锁定是一种在懒汉式单例模式中解决线程安全问题的常用方法。
- 通过在获取实例的方法内使用双重检查锁定机制,可以避免每次都进入同步块,提高性能。
- 在双重检查锁定中,需要注意使用
volatile
关键字修饰实例变量,以确保多线程环境下的可见性和有序性。
- 静态内部类单例模式:
- 静态内部类单例模式是一种常用的线程安全的单例模式实现方式。
- 在静态内部类中创建单例实例,由于静态内部类只在需要时才会被加载,因此实现了懒加载的效果。
- 静态内部类单例模式是线程安全的,因为静态内部类的加载是线程安全的,并且只会加载一次。
main方法
分析public static void main(String[] args)
在Java中,程序的入口点是main()
方法。为了使JVM能够调用main()
方法,它必须具有以下特征:
- 访问权限必须是
public
:main()
方法必须声明为public
,以便JVM能够访问它。 - 方法必须是
static
:main()
方法必须声明为static
,因为在调用main()
方法时,JVM无需创建类的实例。 - 方法参数:
main()
方法接受一个String
类型的数组参数(通常命名为args
),该数组保存执行Java命令时传递给程序的参数。
命令行参数以及IDEA如何设置使用终端运行
实例变量赋值顺序
总结···类的加载顺序
- 类的加载顺序:
- 在创建子类对象时,会先加载父类,然后再加载子类。
- 静态初始化块按照它们在代码中的顺序执行,先执行父类的静态初始化块,然后执行子类的静态初始化块。
- 普通初始化块和构造方法按照它们在代码中的顺序执行,先执行父类的普通初始化块和构造方法,然后执行子类的普通初始化块和构造方法。
分析
- 静态初始化块(
static
代码块):- 静态初始化块在类加载时执行,且只执行一次。
- 静态初始化块按照它们在代码中的顺序执行。
- 静态初始化块用于初始化类级别的静态成员变量或执行其他静态操作。
- 普通初始化块(初始化代码块):
- 普通初始化块在创建对象时执行,每次创建对象都会执行一次。
- 普通初始化块按照它们在代码中的顺序执行,在构造方法之前执行。
- 普通初始化块用于初始化实例级别的成员变量或执行其他实例级别的操作。
- 构造方法:
- 构造方法在创建对象时执行,用于完成对象的初始化。
- 构造方法可以重载,通过不同的参数列表来区分。
- 在构造方法中,可以通过
super()
调用超类的构造方法,或者通过this()
调用同一类中的其他构造方法。
关键字final
关键字final的意义
- 不可修改性:
final
可以将实体声明为不可修改的,确保其数值或行为不会被改变。 - 安全性和稳定性:
final
可以提供代码的安全性和稳定性,防止意外的修改和不必要的变动。 - 性能优化:
final
可以用于性能优化,编译器可以进行更多的优化,提高执行效率。 - API 设计:在设计 API 时,使用
final
可以提供清晰的接口定义,减少对外部代码的依赖,促进代码的可维护性。
关键字 final
用于声明不可变的实体,包括类、方法和变量。
final
类:- 声明为
final
的类**不能被继承**,即它是最终类。 final
类中的方法默认为final
,但可以被子类继承,除非它们被子类重写并标记为final
。- 声明为
final
的类通常用于安全性、稳定性或效率等方面的考虑。
- 声明为
final
方法:- 声明为
final
的方法不能被子类重写或覆盖。 final
方法在父类中定义实现,并且子类不能对其进行更改。final
方法可以被继承,但无法被子类修改。
- 声明为
final
变量:- 声明为
final
的变量是一个常量,一旦赋予初始值后,就不能再改变。 final
变量必须在声明时初始化,可以通过直接赋值或构造方法进行初始化。final
变量通常使用大写字母表示,并使用下划线分隔单词(例如:MAX_SIZE
)。final
变量可以是基本数据类型(如int
、char
等)或引用类型(如String
、Object
等)。- 对于引用类型的
final
变量,引用本身是不可变的,但是对象的内部状态仍然可以修改。
- 声明为
final
参数:- 声明为
final
的方法参数表示该参数在方法内部不可修改。 - 使用
final
参数可以确保方法中不会意外地修改参数的值。
- 声明为
final
和继承:- 声明为
final
的类不能被继承。 - 声明为
final
的方法不能被子类重写。 - 声明为
final
的变量在被赋值后不能再修改。
- 声明为
final
关键字的使用场景
包括但不限于以下几种情况:
- 希望确保类不被继承或方法不被重写。
- 希望创建不可变的常量。
- 希望避免参数在方法内部被修改。
- 用于优化代码,例如在方法内部缓存计算结果。
关键字abstract(抽象类或抽象方法)
关键字 abstract
用于声明抽象类和抽象方法
- 抽象类:
- 抽象类是用
abstract
关键字声明的类。 - 抽象类不能被实例化,即不能创建抽象类的对象。
- 抽象类可以包含抽象方法、普通方法、静态方法、构造方法和成员变量。
- 抽象类可以有构造方法,但不能直接通过构造方法创建对象,只能通过其子类来创建对象。
- 抽象类可以拥有抽象方法和非抽象方法的具体实现。
- 抽象类可以被继承,子类需要实现抽象类中的所有抽象方法或声明自身为抽象类。
- 抽象类是用
- 抽象方法:
- 抽象方法是用
abstract
关键字声明的方法,没有方法体。 - 抽象方法在抽象类中声明,子类必须实现抽象方法。
- 抽象方法用于定义方法的接口,具体的实现由子类提供。
- 子类继承抽象类后,必须实现父类中的所有抽象方法,除非子类也是抽象类。
- 抽象方法不能是私有、静态、final 或 native。
- 抽象方法是用
- 抽象类和抽象方法的作用:
- 抽象类提供了一种模板或基础,用于派生具体子类。
- 抽象类可以定义抽象方法,强制子类实现这些方法,确保方法在各个子类中的一致性。
- 抽象类可以包含具体的方法实现,提供通用的功能或默认的行为。
- 抽象类可以作为多态的基础,通过父类引用指向子类对象。
模板设计模式
概念
模板设计模式(Template Design Pattern)是一种行为型设计模式,用于定义算法的框架结构,将算法的具体实现延迟到子类中。模板设计模式通过定义一个抽象类或接口作为算法的模板,并在其中定义算法的骨架,而将一些具体步骤的实现延迟到子类中。
在模板设计模式中,通常包含以下角色:
- 抽象类(Abstract Class):抽象类定义了算法的模板,其中包含了算法的骨架和一些抽象方法或钩子方法。抽象类负责控制算法的执行流程,并定义了算法中不变的部分。
- 具体类(Concrete Class):具体类是抽象类的子类,实现了抽象方法或钩子方法,完成算法中可变的部分。具体类实现了抽象类中定义的算法模板,并提供了具体的实现细节。
细节分析
-
角色:
- 模板(Template):定义了算法的骨架,包含一个或多个抽象方法,用于延迟实现的步骤。
- 具体模板(Concrete Template):实现了模板中定义的抽象方法,完成算法中的具体步骤。
-
工作原理:
- 模板设计模式通过定义一个模板方法来实现算法的骨架。模板方法包含了算法的主要逻辑,它调用了多个抽象方法和具体方法。
- 抽象方法由模板定义,用于延迟实现的步骤。具体方法在模板中有默认的实现,也可以由子类进行重写。
- 子类通过继承模板并实现其中的抽象方法来完成算法的具体实现。
-
优点:
- 提供了一种封装算法的方式,使得算法的骨架可以在不改变结构的情况下进行扩展和修改。
- 遵循了开闭原则,模板方法定义了算法的骨架,具体实现可以在子类中进行扩展,而不需要修改模板方法本身。
- 通过模板方法的定义和抽象方法的实现,实现了算法的复用和代码的共享。
关键字interface(接口)
interface
关键字的详细信息
- 声明接口:
- 使用
interface
关键字来声明接口。 - 接口的名称应该采用大写字母开头的驼峰命名法。
- 使用
- 方法声明:
- 接口中的方法只有方法签名,没有具体的实现。
- 方法声明包括方法的返回类型、方法名和参数列表。
- 方法默认为公共的(
public
),可以省略访问修饰符。
- 常量声明:
- 接口中可以定义常量,常量被隐式声明为
public static final
。 - 常量的命名应该使用全大写字母和下划线的命名规范。
- 接口中可以定义常量,常量被隐式声明为
- 默认方法(Default Methods):
- 从Java 8开始,接口可以包含默认方法,使用
default
关键字进行声明和实现。 - 默认方法提供了接口的默认实现,实现类可以直接使用或重写默认方法。
- 默认方法可以通过接口的实例调用,也可以在实现类中被调用。
- 从Java 8开始,接口可以包含默认方法,使用
- 静态方法(Static Methods):
- 从Java 8开始,接口可以包含静态方法,使用
static
关键字进行声明和实现。 - 静态方法是接口的类级别方法,可以直接通过接口名调用,无需实例化接口。
- 从Java 8开始,接口可以包含静态方法,使用
- 继承接口(Interface Inheritance):
- 接口可以继承其他接口,使用
extends
关键字。 - 一个接口可以继承多个接口,采用逗号分隔。
- 继承的接口中的方法和常量会被继承到子接口中。
- 接口可以继承其他接口,使用
- 实现接口(Interface Implementation):
- 类可以通过使用
implements
关键字来实现接口。 - 实现接口要求类提供接口中定义的所有方法的具体实现。
- 类可以实现多个接口,使用逗号分隔。
- 类可以通过使用
- 接口与抽象类(Interface vs Abstract Class):
- 接口只能包含常量和方法声明,没有字段和具体实现。
- 抽象类可以包含字段、方法和具体实现。
- 类可以实现多个接口,但只能继承一个抽象类。
- 接口的使用场景:
- 定义契约和协议,规范类的行为和能力。
- 实现多态,允许一个类实现多个接口。(跳转接口的多态)
- 接口隔离,将系统功能进行拆分,降低类之间的耦合度。
- 规范约束,提供代码的规范和可读性。
接口(interface)和抽象类(abstract class)
特点 | 接口 (interface) | 抽象类 (abstract class) |
---|---|---|
实例化 | 不能实例化 | 不能实例化 |
构造函数 | 不能包含构造函数 | 可以包含构造函数 |
字段 | 不能包含字段 | 可以包含字段 |
方法 | 只包含方法声明,没有方法实现 | 可以包含方法声明和方法实现 |
多继承 | 支持多继承 | 不支持多继承 |
单继承 | 可以继承多个接口 | 只能继承一个抽象类 |
默认方法 | 可以包含默认方法 | 不支持默认方法 |
静态方法 | 可以包含静态方法 | 可以包含静态方法 |
访问修饰符 | 默认为公共(public) | 可以使用各种访问修饰符 |
构建范围 | 用于定义契约和协议,规范类的行为和能力 | 用于抽象概念和部分实现,提供共享代码和行为的能力 |
实现方式 | 类实现接口时使用implements关键字 | 类继承抽象类时使用extends关键字 |
设计目的 | 接口隔离,实现多态 | 提供共享代码和行为的能力,提供抽象概念 |
实例化要求 | 类要实现接口中定义的所有方法 | 类可以选择性地实现抽象类中的方法 |
常见设计模式 | 简单工厂、工厂方法、代理模式 | 模板方法设计模式 |
枚举类
内部类
四种类型
内部类是指在一个类的内部定义的类。Java中的内部类有四种类型:成员内部类、静态内部类、局部内部类和匿名内部类。
- 成员内部类(Member Inner Class):
- 定义:成员内部类是定义在类的内部,并且与类的成员变量和方法同级别的类。
- 特点:
- 成员内部类可以访问外部类的所有成员变量和方法,包括私有成员。
- 成员内部类可以使用访问控制修饰符进行修饰(public、private等)。
- 成员内部类的实例必须依赖于外部类的实例,即需要通过外部类的实例来创建内部类的对象。
- 使用情况:
- 成员内部类适合用于需要访问外部类的成员变量和方法,并且与外部类有密切关联的情况。
- 静态内部类(Static Inner Class):
- 定义:静态内部类是定义在类的内部,但使用 static 关键字修饰的类。
- 特点:
- 静态内部类与外部类的实例无关,可以直接创建静态内部类的对象。
- 静态内部类可以访问外部类的静态成员变量和方法,但不能直接访问外部类的非静态成员。
- 静态内部类可以拥有自己的静态成员变量和方法。
- 使用情况:
- 静态内部类适合用于与外部类没有紧密关联的情况,或者需要创建独立于外部类实例的对象的情况。
- 局部内部类(Local Inner Class):
- 定义:局部内部类是定义在方法内部的类。
- 特点:
- 局部内部类只在所在方法中可见,外部方法无法访问局部内部类。
- 局部内部类可以访问方法中的 final 或 effectively final 的局部变量。
- 局部内部类不能声明静态成员变量和方法。
- 使用情况:
- 局部内部类适合用于需要在方法内部定义一个辅助类,且该类只在该方法内部使用的情况。
- 匿名内部类(Anonymous Inner Class):
- 定义:匿名内部类是没有显式定义类名的内部类,通常直接作为参数或方法内部的一部分来使用。
- 特点:
- 匿名内部类没有类名,直接定义在方法内部或作为参数传递。
- 匿名内部类可以继承一个类或实现一个接口。
- 匿名内部类可以访问外部类的成员变量和方法,以及方法中的 final 或 effectively final 的局部变量。
- 使用情况:
- 匿名内部类适合用于需要定义一次性的类,不需要命名或重复使用的情况,比如创建事件处理器、实现接口等。
Annotation(注解)和元注解
JUnit单元测试(@Test)
包装类
用途
- 编码过程中只接收对象的情况,比如List中只能存入对象,不能存入基本数据类型;比如一个方法的参数是Object时,不能传入基本数据类型,但可以传入对应的包装类; 比如泛型等等。
- 基本数据类型没有toString()方法等
介绍
包装类(Wrapper Class)是Java中提供的一组类,用于将基本数据类型(如int、char、boolean等)封装成对象。每种基本数据类型都有对应的包装类,包装类提供了许多方法和功能,使得基本数据类型可以像对象一样进行操作。
- 特点和功能:
- 封装:包装类将基本数据类型封装成对象,使其具有对象的特性,如可以作为方法的参数和返回值,可以参与对象的存储和传递等。
- 自动装箱和拆箱:Java提供了自动装箱和拆箱机制,可以自动在基本数据类型和对应的包装类之间进行转换。
- 不可变性:包装类的实例是不可变的,即一旦创建就无法修改其值。
- 包装类提供了许多方法用于操作和处理基本数据类型,如比较、转换、格式化等。
- 包装类还提供了常量和静态方法,如最大值、最小值、类型转换等。
包装类和基本数据类型之间的转换
- 自动装箱(Autoboxing):
- 自动装箱是指将基本数据类型自动转换为对应的包装类对象。
- 自动拆箱(Unboxing):
- 自动拆箱是指将包装类对象自动转换为对应的基本数据类型。
- 包装类提供的方法进行转换
- valueOf()方法:用于将基本数据类型转换为对应的包装类对象。
- xxxValue()方法:用于将包装类对象转换为基本数据类型的值。
- parseXxx()方法:用于将字符串转换为基本数据类型的值。
注意事项
- 在进行包装类与基本数据类型之间的比较时,应使用包装类提供的 equals() 方法,而不是直接使用 “==” 进行比较。
- 在使用自动拆箱时,需要确保包装类对象不为 null,否则会抛出 NullPointerException 异常。
包装类缓存优化:Java中常用数据的缓存技术
Java对部分经常使用的数据采用缓存技术,在类第一次被加载时创建缓存和数据。当使用等值对象时直接从缓存中获取,从而提高了程序执行性能(通常只对常用数据进行缓存)。
包装类与基本数据类型的比较大小
在Java中,包装类与基本数据类型之间可以进行相等性比较。对于基本数据类型,可以直接使用关系运算符(如>
、<
、==
等)进行比较。而对于包装类,则需要使用equals()
方法进行比较。
在某些情况下,使用valueOf()
方法创建的包装类对象可以利用缓存技术,使得在一定范围内的比较结果为相等。
各个包装类的缓存范围和一些特殊注意事项:
- Integer类型有缓存-128到127的对象。缓存上限可以通过配置JVM参数来更改。
- Byte、Short、Long类型有缓存-128到127的对象。
- Character缓存0到127的对象。
- Boolean缓存TRUE和FALSE的对象。
需要注意的是,只有使用valueOf()
方法构造对象时才会使用缓存。使用new
方法等方式创建对象不会使用缓存。
故当使用valueOf()
方法创建包装类对象时,与基本数据类型进行大小比较时,在缓存范围内的值将被认为是相等的。这是因为它们引用了缓存中的同一个对象。
相关文章:

Java面向对象高级
文章目录 面向对象高级Object类的常用方法常用方法一(面向对象阶段)** 和 equals 的区别** 关键字native**单例设计模式(Singleton)**前情回顾(学习基础)静态修饰符Static设计模式概念开发步骤**两种实现方…...

渗透测试信息收集方法和工具分享
文章目录 一、域名收集1.OneForAll2.子域名挖掘机3.subdomainsBurte4.ssl证书查询 二、获取真实ip1.17CE2.站长之家ping检测3.如何寻找真实IP4.纯真ip数据库工具5.c段,旁站查询 三、端口扫描1.端口扫描站长工具2.masscan(全端口扫描)nmap扫描3.scanport4.端口表5.利…...

Unity打包出来的APK文件有问题总结
一、Unity打包出来的APK文件安装失败,提示安装失败(-108),或者是提示“包含病毒:a.gray.Bulimia.b” 有可能是遇到如上图所示的问题,提示安装失败(-108)。 有可能是遇到如上图所示的…...

记录:移动设备软件开发(Activity的显式启动和隐式启动)
目录 Intent对象简述Intent的作用Intent开启Activtiy显式启动Activity隐式启动Activity Intent对象简述 Android的应用程序包含三种重要组件:Activity、Service、BroadcastReceiver,应用程序采用了一致的方式来启动它们——都是依靠Intent来启动的&…...

面试题库(十一):MQ和分布式事务
MQ mq 通知时,消费者没消费到怎么办简单聊聊消息中间件?你了解那些具体的消息中间件产品?mq的消费端是怎么处理的? 整理一下你的消费端的整个处理逻辑流程,然后说说你的ack是在哪里返回的。按照你这样画的话,如果数据库突然宕机,你的消息该怎么确认已经接收? 那如果发送…...

Linux日期和时间管理指南:日期、时间、时区、定时任务和时间同步
文章目录 Linux日期和时间管理指南1. 简介1.1 Linux 日期和时间的重要性1.2 日期管理的需求 2. 查看当前日期和时间2.1 date 命令2.2 cal 命令2.3 查看硬件时钟 3. 设置系统日期和时间3.1 设置日期3.2 设置时间3.3 设置硬件时钟 4. 时区管理4.1 查看当前时区4.2 修改系统时区4.…...

tsar-性能监控工具
简介 tsar是淘宝自己开发的一个采集工具,主要用来收集服务器的系统信息(如cpu,io,mem,tcp等),以及应用数据(如squid haproxy nginx等)。收集到的数据存储在磁盘上&#…...

【Linux】系统编程简单线程池(C++)
目录 【1】线程池概念 【1.1】线程池 【1.2】线程池的应用场景 【1.3】线程池的种类 【1.4】线程池示例 【2】线程池代码 【1】线程池概念 【1.1】线程池 一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程&a…...

数据结构之道:如何选择适合你的数据存储
文章目录 第1节:数据结构的基本原理1.1 时间复杂度和空间复杂度1.2 数据的访问方式1.3 数据的增删操作 第2节:常见的数据结构2.1 数组(Array)2.2 链表(Linked List)2.3 栈(Stack)2.4…...

MySQL定时删除XX天数据
写在前面 定时删除数据方式有多种方法,在实际工作中很多人可能会通过编码实现,也有人可能会通过脚本定时执行SQL进行定时删除对应数据。 今天使用MySQL自带的删除策略。 MYSQL删除策略 从MySQL5.1.6起,增加了一个非常有特色的功能–事件调…...

vue在js文件中调用$notify
我们在vue组件中可以直接 this.$notify({title: 修改成功,type: success,duration: 2500 })但在js中 我们this的指向就会发生一些不同 但是 其实 学过构造函数和原型链的人会很好理解这一点 每一个vue组件都是通过 vue构造出来的一个实例 所以 他们的this都是指向当前实例对象…...

C++从入门到精通
目录 C 语言特性C 学习大纲初级阶段1. 基础概念2. 数据类型和变量3. 运算符和表达式4. 控制流程 中级阶段5. 函数和模块化编程6. 数据结构7. 面向对象编程(OOP) 高级阶段8. 文件操作和流9. 模板和泛型编程10. 多线程和并发编程11. 高级主题 实际项目 C 语…...

2023网络安全面试题(附答案)+面经
前言 随着国家政策的扶持,网络安全行业也越来越为大众所熟知,相应的想要进入到网络安全行业的人也越来越多,为了拿到心仪的Offer之外,除了学好网络安全知识以外,还要应对好企业的面试。 所以在这里我归纳总结了一些网…...

数据结构_红黑树
1、二叉树 每一个分支不能超过两个 2、 排序数/查找树 在二叉树的基础上,元素是有大小顺序的左 子树 小,右 子树 大 3、平衡树 左孩子数 和 右孩子数 相等 4、不平衡树 5、 红黑树 特点:趋近于平衡树,查询的速度非常的快…...

一百八十八、Hive——HiveSQL查询表中的日期是星期几(亲测,附截图)
一、目的 指标需要查询以工作日和周末维度的数据统计,因此需要根据数据的日期判断这一天属于星期几,周一到周五为工作日,周六到周日为周末 二、SQL查询 (一)SQL语句 selectday,case when pmod(datediff(create_tim…...

基础题——数组
输入一个电子邮箱,检查用户输入的字符串是否为有效的电子邮件地址 正确的邮箱地址: 必须包含字符,不能是开头或结尾 必须以 .com结尾 和.com之间必须有其他字符 public static void main(String[] args) {Scanner sc new Scanner(System.in…...

Qt地铁智慧换乘系统浅学( 一 )存储站点,线路信息
存储 定义所需要的容器定义最大最小经纬度[统计站点信息 在经纬度网站](https://map.jiqrxx.com/jingweidu/)读取统计的信息存储到容器其他的一些相关函数debug 显示存储的信息更新最小最大经纬度的函数获取两点之间的距离 根据经纬度 定义所需要的容器 extern QMap<QStrin…...

Python之xToolkit库
文章目录 一、xToolkit是什么?二、准备工作1.引入库2.导入数据 三、使用时间模块-xdatetime判断时间格式是否正确get方法获取时间戳获取年月日时分秒时间推移计算时间替换时间扩展两个时间的差值开始与结束时间时间是否在指定区间中 字符串模块-xstring字符串格式校…...

2w+深度梳理!全网最全NLP面试题总结!
目录 技术交流群 1、命名实体识别常见面试篇2、关系抽取常见面试篇3、事件抽取 常见面试篇4、NLP 预训练算法常见面试篇5、Bert 常见面试篇6、文本分类 常见面试篇7、文本匹配 常见面试篇8、问答系统常见面试篇FAQ 检索式问答系统常见面试篇问答系统工具篇常见面试篇 9、对话系…...

Spring 学习(五)JavaConfig 实现配置
1. 使用 JavaConfig 实现配置 JavaConfig 是 Spring 项目的一个子项目,Spring 4 后成为核心功能。 注意: 如果开启包扫描,加载配置类以后就可以通过反射拿到配置类中的对象了。Bean 只写在方法上,返回的是一个对象,但…...

【Synapse数据集】Synapse数据集介绍和预处理,数据集下载网盘链接
【Segment Anything Model】做分割的专栏链接,欢迎来学习。 【博主微信】cvxiaoyixiao 本专栏为公开数据集的介绍和预处理,持续更新中。 文章目录 1️⃣Synapse数据集介绍文件结构源文件样图文件内容 2️⃣Synapse数据集百度网盘下载链接官网下载登录下…...

【运动规划算法项目实战】Dynamic Window Approach算法(附ROS C++代码)
文章目录 前言一、简介1.1 DWA算法原理1.2 DWA算法的应用场景1.4 DWA算法的优缺点1.4.1 优点1.4.2 缺点二、代码实现2.1 算法细节2.1.1 DWA的控制输入:2.1.2 动态窗口的计算2.1.3 评价函数的优化2.2 程序说明2.21 PathGenerator2.2.2 WaypointAction2.2.3 使用方法2.3 代码演示…...

第十四届蓝桥杯大赛软件赛决赛 C/C++ 大学 B 组 试题 A: 子 2023
[蓝桥杯 2023 国 B] 子 2023 试题 A: 子 2023 【问题描述】 小蓝在黑板上连续写下从 1 1 1 到 2023 2023 2023 之间所有的整数,得到了一个数字序列: S 12345678910111213 ⋯ 20222023 S 12345678910111213\cdots 20222023 S12345678910111213⋯2…...

Unity 场景淡入淡出效果
一. 使用Dotween,建议使用我的方式 FindObjectOfType<SceneFadeInAndOut>().FadeIn(() > { Debug.Log("Fade in MenuStart Scene"); }); using DG.Tweening; using System; using System.Numerics; using UnityEngi…...

快速使用Spring Cache
哈喽~大家好,这篇我们来看看快速使用Spring Cache。 🥇个人主页:个人主页 🥈 系列专栏:【日常学习上的分享】 🥉与这篇相关的文章: R…...

Scrum敏捷开发培训内训:提升团队能力和效率的重要途径
在当今软件开发领域,Scrum敏捷开发方法越来越受到重视。Scrum是一种以团队协作为基础,注重灵活性和快速响应变化的方法。 为了帮助团队更好地掌握Scrum敏捷开发,培训变得越来越重要。Scrum敏捷开发方法注重高效协作、快速迭代和持续改进。通…...

kaggle新赛:Optiver 美股价格预测赛题解析
赛题名称:Optiver - Trading at the Close 赛题链接:https://www.kaggle.com/competitions/optiver-trading-at-the-close 赛题背景 证券交易所是快节奏、高风险的环境,每一秒都很重要。随着交易日接近尾声,强度不断升级&#…...

Vue 学习笔记 错误ResizeObserver loop completed with undelivered notifications
环境Vue3 Ts 使用了el-table 后,容易出现如下错误 ERROR ResizeObserver loop completed with undelivered notifications. at handleError (webpack-internal:///./node_modules/webpack-dev-server/client/overlay.js:299:58) at eval (webpack-internal:///./nod…...

Wi-Fi直连分享:Android设备间的高速连接
Wi-Fi直连分享:Android设备间的高速连接 引言 随着无线局域网(Wi-Fi)的普及和发展,使用Wi-Fi直连技术(P2P)在没有中间接入点的情况下实现设备间直接互联成为可能。通过Wi-Fi直连,具备相应硬件…...

LeetCode 面试题 05.06. 整数转换
文章目录 一、题目二、Java 题解 一、题目 整数转换。编写一个函数,确定需要改变几个位才能将整数A转成整数B。 示例1: 输入: A 29 (或者0b11101), B 15(或者0b01111) 输出: 2 示例2: 输入&a…...