Java 知识量:11 - 45 - 220
引用类型(Reference Types)是指在Java中需要通过引用来访问的数据类型。引用类型在Java中主要包括类(Class)、接口(Interface)、数组(Array)和枚举(Enum)。
引用类型的值本质上是一个指针,它存储的是实际数据对象在内存中的地址。当我们声明一个引用类型的变量时,实际上是在声明一个指针,该指针指向实际的数据对象。
在Java中,所有的对象都是引用类型,包括自定义的类和接口、数组以及枚举类型。创建一个对象时,实际上是在堆内存中创建了一个实际的数据对象,然后将其地址赋值给引用类型的变量。
引用类型在Java中有很多重要的特性,例如继承、多态和垃圾回收等。继承允许创建一个新类,它可以从已有的类派生出来,并添加或覆盖属性和方法。多态允许以统一的方式处理不同的对象,垃圾回收则自动管理内存,释放不再使用的对象所占用的内存空间。
基本类型(又称原始类型)和引用类型的主要区别有:
存储位置:基本类型的数据直接存储在栈内存中,而引用类型的数据存储在堆内存中。
存储方式:基本类型存储的是实际的数据值,而引用类型存储的是实际数据的内存地址。
赋值:基本类型赋值时,会创建一个新的值,原来的值不会改变;而引用类型赋值时,只是将引用指向新的对象,原来的对象不会被改变。
继承:基本类型不可以被继承,而引用类型可以被继承。
默认值:基本类型有默认的初始值(例如,int的默认值为0),而引用类型的默认值为null。
包装类:基本类型有对应的包装类,例如int的包装类为Integer,而引用类型没有包装类。
性能:基本类型的操作通常比引用类型的操作更快,因为它们在栈中直接存储数据,而引用类型需要在堆中查找实际数据。
安全性:基本类型比引用类型更安全,因为基本类型不可能引用到null。
在Java中,对象和引用是面向对象编程的两个核心概念。对象是类的实例,而引用是对象在内存中的地址。
Java中的对象是通过引用进行操作的。当创建一个对象并将其赋值给一个变量时,实际上是将该对象的引用赋值给了变量。变量中存储的是对象的内存地址,而不是对象本身。
例如,下面的代码创建了一个字符串对象,并将其赋值给了两个不同的变量:
String str1 = "Hello"; String str2 = "Hello";
实际上,这段代码在内存中创建了一个字符串对象,然后将该对象的引用分别赋值给了str1和str2。因此,str1和str2都指向同一个字符串对象。
当需要复制一个对象时,实际上需要复制该对象的内容。这可以通过使用clone()方法或copy constructor来实现。这些方法会创建一个新的对象,并将原始对象的值复制到新对象中。
例如,下面的代码使用clone()方法复制了一个字符串对象:
String str1 = "Hello"; String str2 = str1.clone();
这段代码创建了两个不同的字符串对象,它们具有相同的值。
需要注意的是,对于可变的对象(例如数组或对象的字段),复制引用并不会复制对象的内容。因此,如果修改了一个对象的内容,另一个引用该对象的变量也会受到影响。这是因为它们都指向同一个对象。
为了避免这种情况,可以使用深拷贝(deep copy)来复制对象及其内容。深拷贝会创建一个新的对象,并将原始对象的所有字段复制到新对象中。这可以通过手动实现,或者使用库如Apache Commons Lang的SerializationUtils.clone()方法来实现。
比较对象通常需要使用equals()方法。equals()方法用于比较两个对象是否相等。默认情况下,equals()方法比较的是两个对象的引用,即它们是否指向内存中的同一个对象。但是,可以重写equals()方法来比较两个对象的内容是否相等。
例如,如果有一个Person类,其中包含name和age属性,可以重写equals()方法来比较两个Person对象的name和age属性是否相等:
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Person)) { return false; } Person other = (Person) obj; return this.name.equals(other.name) && this.age == other.age; } }
在上面的例子中,首先检查两个对象是否是同一个对象(即它们的引用是否相等),如果是,则返回true。然后,检查传入的对象是否是Person类型的,如果不是,则返回false。最后,将传入的对象转换为Person类型,并比较两个Person对象的name和age属性是否相等。如果相等,则返回true,否则返回false。
除了使用equals()方法外,还可以使用==操作符来比较对象的引用是否相等。但是,在比较对象的内容是否相等时,应该使用equals()方法。
Java的包装类是用来封装基本数据类型的对象,以便在面向对象编程中使用。每个包装类都对应一个基本数据类型,例如Integer对应int,Double对应double等。
装包(boxing)和拆包(unboxing)是Java中特有的术语,分别表示将基本数据类型转换为包装类对象,以及将包装类对象转换为基本数据类型。
装包(boxing):
int num = 10; Integer integerNum = Integer.valueOf(num); // 装包
拆包(unboxing):
Integer integerNum = Integer.valueOf(10); int num = integerNum; // 拆包
在上述例子中,装包是将int类型的变量num转换为Integer对象,而拆包则是将Integer对象integerNum转换为int类型的变量num。
值得注意的是,从Java 5开始,装包和拆包操作可以自动进行,无需显式调用valueOf()方法。例如:
int num = 10; Integer integerNum = num; // 自动装包 Integer integerNum = Integer.valueOf(10); int num = integerNum; // 自动拆包
在上述例子中,编译器会自动进行装包和拆包操作,使得代码更加简洁易读。
Copyright © 2017-Now pnotes.cn. All Rights Reserved.
编程学习笔记 保留所有权利
MARK:3.0.0.20240214.P35
From 2017.2.6