面向对象(二)
《疯狂Java讲义》学习笔记
基本数据类型对应的包装类
基本数据类型 | 对应的包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
自动装箱
-
把一个基本数据类型变量直接赋值给对应的包装类变量或者是
Object
变量 -
包装类实现基本类型变量和字符串之间的转换:
- 利用包装类的
parseXxx(String str)
静态方法 - 利用包装类提供的
Xxx(String str)
构造器
- 利用包装类的
-
基本数据类型转换成字符串:
String
类重载的valueOf()
方法- 将基本类型变量和英文双引号(
""
)进行连接运算
-
虽然包装类型的变量是引用数据类型,但包装类的实例可以与数值类型进行比较,这种比较是直接取出包装类实例所包装的数值进行比较的。只有两个包装类的类型一样才可以比较
-
Java7的所有包装类都提供了
compare(xxx value1,xxx value2)
方法来比较两个基本类型变量的大小 -
boolean
类型的变量比较时:true
>false
-
Java8增强的无符号数运算:
String UnsingedString(int/Integer i)
:把int
或Integer
转成无符号数字符串
==
和 equals
方法
使用 ==
来判断两个变量是否相等时:
1. 如果两个变量是基本类型变量,且数值类型相等,如果两个变量值相等,就返回 true
2. 对于引用类型变量:如果两个变量指向同一个对象,==
才会返回 true
//String str = "Hello";和String str = new String("Hello");的区别:
//JVM使用常量池管理这些字符串。
String str = "Hello";
//JVM会先使用常量池管理“Hello”直接量,在调用String的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中
String str = new String("Hello");
String str1 = "疯狂Java";
String str2 = "疯狂";
String str3 = "Java";
String str4 = "疯狂" + "Java";
String str5 = "疯" + "狂" + "Java";
String str6 = str2 + str3;
String str7 = new String("疯狂Java");
System.out.println(str1 == str4); //true
System.out.println(str1 == str5); //true
System.out.println(str1 == str6); //false
System.out.println(str1 == str7); //false
使用 equals
判断对象是否相等
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj.getClass() == Student.class) {
Student s = (Student) obj;
//根据学生学号判断两个对象是否相等
if (s.sid.equals(this.sid)) {
return true;
}
}
return false;
}
类成员
- 使用对象调用类成员(类方法)时,实际上依然是委托给该类来访问类成员或类方法,因此即使某个实例为
null
,也可以调用类变量
单例类
- 私有化构造器,在类中提供一个静态变量,返回该类的唯一实例
//懒汉式-线程不安全
class Singleton {
private static Singleton instance;
//私有化构造器
private Singleton() {
}
public Singleton getInstancce() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
final
修饰符
final
修饰的成员变量必须由程序员显示的指定初始值- 对于类变量:必须在静态初始化块中,或者声明该类变量时指定初始值
- 对于实例变量:在非静态初始化块,声明该实例变量或在构造器中指定初始值
final
修饰局部变量:可以不在定义时初始化,但只能初始化一次final
修饰形参时:初始化工作是由系统根据调用该函数是传入的实参进行的初始化final
修饰基本类型的变量和引用类型的变量- 不能对基本类型的变量重新赋值
- 对于引用类型的变量:
final
只保证这个引用类型的变量所引用的地址不发生改变,即一直引用同一个变量,但这个对象完全可以改变
- 可执行“宏替换”的
final
变量:
对于一个final
变量,不管它是类变量、实例变量,还是局部变量,只要定义该变量时使用了final
修饰符修饰,并在定义该final
类变量时指定了初始值,而且该初始值可以在编译时就被确定下来,那么这个final
变量本质上已经不再是变量,而是相当于一个直接量。
public class FinalLocalTest {
public static void main(String[] args) {
//定义一个普通局部变量,并设置初始值为5
final int a = 5;
//对于这个程序来说,变量a其实根本就不存在,
//当程序执行 System.out.println(a); 代码时,
// //实际转换为执行 System.out.println(5);
System.out.println(a);
}
}
在定义变量时使用 final
修饰,并且在定义时就显示赋值;在调用该变量时系统会直接使用该变量的值
final
方法:不能被子类重写,本类可以重载该方法final
类:final
修饰的类表示该类不可以有子类
不可变类
使用 private
和 final
修饰,并且不提供 setter
方法,只在构造器中初始化实例变量
class Name {
private String firstName;
private String lastName;
public Name() {
}
//省略getter和setter
public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
class Person {
private final Name name;
public Person(Name name) {
//设置 name 实例变量为临时创建的 Name 对象,该对象的 firstName 和 lastName
//与传入的 name 参数的 firstName 和 lastName 相同
//这里创建一个新的对象赋给this.name 是因为name为引用类型的变量,因此完全可以更改属性值
this.name = new Name(name.getFirstName(), name.getLastName());
}
public Name getName() {
// 返回一个匿名对象该对象的 firstName 和 lastName
// 与对象里的 name 的 firstName 和 lastName 相同
// 因为返回的是对象的地址,因此完全可以在根据返回的对象引用改变对象的属性
return new Name(this.name.getFirstName(), this.name.getLastName());
}
}
缓存实例的不可变类
- 创建缓存实例的不可变类:
- 定义一个数组当做缓存池
- 定义一个变量记录缓存实例在缓存池中的位置
- 私有化构造器
- 定义一个方法用于创建缓存实例,并放在缓存池中
public class CacheImmutableTest {
public static void main(String[] args) {
CacheImmutable c1 = CacheImmutable.valueOf("hello");
CacheImmutable c2 = CacheImmutable.valueOf("hello");
System.out.println(c1 == c2);// true
}
}
class CacheImmutable {
private static int MAX_SIZE = 10;
// 使用数组缓存已有的实例
private static CacheImmutable[] cache = new CacheImmutable[MAX_SIZE];
// 记录缓存实例在缓存中的位置cache[pos-1]是最新的缓存实例
private static int pos = 0;
private final String name;
private CacheImmutable(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static CacheImmutable valueOf(String name) {
// 遍历缓存对象
for (int i = 0; i < cache.length; i++) {
if (cache[i] != null && cache[i].getName().equals(name)) {
return cache[i];
}
}
// 如果缓存池已满
if (pos == MAX_SIZE) {
// 把缓存池的第一个对象覆盖
cache[0] = new CacheImmutable(name);
pos = 1;
} else {
// 把新创建的对象缓存起来,pos+1
cache[pos++] = new CacheImmutable(name);
}
return cache[pos - 1];
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj != null && obj.getClass() == CacheImmutable.class) {
CacheImmutable cache = (CacheImmutable) obj;
return cache.getName().equals(name);
}
return false;
}
@Override
public int hashCode() {
return this.getName().hashCode();
}
}