文章目录
- 3.4 类的使用(下)
- 3.4.5 this指针
- 3.4.6 对象的回收
- 3.4.7 包
- 3.4.8 import
- 3.4.9 类的访问控制
3.4 类的使用(下)
3.4.5 this指针
- 每一个方法内都有一个隐含的指针,指向“调用该方法的当前对象”,称为this指针。this指针只能在方法内部使用,通俗地解释就是,这个this指针是每一个 方法内置的,当对象调用某个方法时,它的this指针就指向该对象了,如果不用它, 就感觉不出它的存在
- this 指针常用于访问对象的数据、方法,也可以作为引用类型的返回值使用。
- 1) this指针的用法1:代替对象,访问对象的数据。
示例:在Product类的构造方法中把隐藏的this指针显式地写出来,使其指向调用此方法的对象。
Product(int id, String nm, String catag, double price) {
this.ID = id;//this指针指向调用该方法的对象
this.name = nm;
this.catagories = catag;
this.productPrice = price;
}
当系统自动调用构造方法生成对象ipad时,构造方法里的this指针便指向了ipad,此时,this.id 等同于ipad.id, this.name 等同于ipad.name,如此看起来,代码表示的意义更加清晰。
- 2) this 指针的用法2:作为返回值使用,当需要返回一个对象时, 可以在return语句里返回this。
示例:Product.java添加- -个返回类型为Product的increment()方法,返回一个this指针,main()中的ipad对象连续调用三次increment()。
public class Product {
int ID;
String name;
String catagories;
double productPrice;
static double totalPrice;//产品总价格
static int totalNumber;//产品总数
int i = 0;//测试this指针
Product(int id, String nm, String catag, double price) {
this.ID = id;//this指针指向调用该方法的对象
this.name = nm;
this.catagories = catag;
this.productPrice = price;
totalPrice = totalPrice + productPrice;//计算总价格
totalNumber++;//每创建一个product对象,totalNumber加一
}
Product increment(){
i++;
return this;
}
void print(){
System.out.println("i = " + i);
}
}
public class Sample{
public static void main(String[] args) {
Product huawei = new Product();
huawei.increment().increment().increment().print();
}
}
运行结果
i = 3
huawei.increment() 返回一个this指针,相当于返回一个Product对象,变量i值增加1。因此,huawei 对象每调用一次increment(),皆返回一个Product 对象,i值随着递增1,最后i值为3。
- 3) this指针的用法3:在构造方法中调用另一个构造方法。
可以使用this关键字在一个构造方法中调用另外一个构造方法,通常用参数个数比较少的构造方法调用参数个数多的构造方法。
示例:在不带参数的默认构造方法里调用了带参数的构造方法,调用时,语句this(…)等价于Product(…)。
Product(int id, String nm, String catag, double price) {
this.ID = id;//this指针指向调用该方法的对象
this.name = nm;
this.catagories = catag;
this.productPrice = price;
totalPrice = totalPrice + productPrice;//计算总价格
totalNumber++;//每创建一个product对象,totalNumber加一
}
Product(String nm) {//使用this指针调用构造函数
this(12,nm,"catag",22.3);
}
//测试
Product xiaomi = new Product("xiaomi");
System.out.println(xiaomi);
//运行结果
Product{ID=12, name='xiaomi', catagories='catag', productPrice=22.3}
- this指针在开发中十分好用
3.4.6 对象的回收
- Java 可以任意创建对象,不必考虑不使用时怎样回收。
- 内存是一种紧缺的资源,对象不再使用时应当尽快释放掉。在C语言中,通过调用malloc0与free()实现内存动态分配和释放;在C++ 语言中,则通过new()与delete()来分配和释放内存空间;而Java只需用new分配内存空间,程序员不必考虑释放空间的问题。
- 图3-2显示C/C++、Java 中的所有对象- -律 在内存的堆中分配空间,对象不再使用时,应该释放所占有的内存空间。
与C/C+需要手工释放对象空间不同,Java 额外提供了垃圾回收器( garbage collector),由它负责释放不再使用的内存资源。那么垃圾回收器是如何知道什么时候应该释放资源了呢?
垃圾回收器会跟踪每一-块分配出去的内存空间,自动扫描对象的动态内存区,对不再使用的对象做上标记,当Java虚拟机处于空闲循环时,垃圾回收器会检查已分配的内存空间,然后自动回收每一块无用的内存块, 通常垃圾回收器周期性地释放无用对象使用的内存。
- 对象都是在内存的堆(Heap)中分配所需的储存区域,操作结束后,释放这些空间,但由于这些操作没有固定的顺序,因而容易导致内存产生很多碎片。例如一个对象在完成使命后不能确保立刻清除,甚至有可能当程序结束后,该对象仍然占用内存,成为了内存垃圾。垃圾回收器也不能保证及时清除无用的内存垃圾,当碎片太多时,占满了内存空间,程序也会出现内存不足的情况,这时就需要借助于手工释放资源,Java提供了finalize() 方法来承担这一-任务, 当资源可能被某些对象占用,Java的内存管理系统无法直接
访问,又不能自动释放时,finalize( ) 方法手工释放内存无疑是最佳选择。程序员大部分时间都不会用到此方法,而运行程序库通常会用这种方式控制某些资源。 - finalize( )方法在类
java.lang.Objet
中声明,因此Java中的每-一个类都自动继承了该方法,方便程序释放系统资源,在关闭打开的文件或socket等情况下,都可能会手工调用finalize( )方法。finalize( )声明格式如下:
protected void finalize() throws throwable
3.4.7 包
- Java里的包(package)可看作Java文件目录,是一种文件保存方式,类似于Windows的文件组织形式
- package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包。(若缺省该语句,则指定为无名包)。它的格式为:
package 顶层包名.子包名;
举例:
pack1\pack2\PackageTest.java
package pack1.pack2; //指定类PackageTest属于包pack1.pack2
public class PackageTest{
public void display(){
System.out.println("in method display()");
}
}
- 包对应于文件系统的目录,package语句中,用 “.” 来指明包(目录)的层次;
- 包通常用小写单词标识。通常使用所在公司域名的倒置:com.baidu.xxx
- 包的作用
l 包帮助管理大型软件系统:将功能相近的类划分到同一个包中。比如:MVC的设计模式
l 包可以包含类和子包,划分项目层次,便于管理
l 解决类命名冲突的问题
l 控制访问权限
3.4.8 import
- 为使用定义在不同包中的Java类,需用import语句来引入指定包层次下所需要的类或全部类(.*)。import语句告诉编译器到哪里去寻找类。
- 语法格式:
import 包名.类名;
- 应用举例:
import pack1.pack2.Test; //import pack1.pack2.\;表示引入pack1.pack2包中的所有结构
public class PackTest{
public static void main(String args[]){
Test t = new Test(); //Test类在pack1.pack2包中定义t.display();
}
}
- 注意:
- 在源文件中使用import显式的导入指定包下的类或接口
- 声明在包的声明和类的声明之间。
- 如果需要导入多个类或接口,那么就并列显式多个import语句即可
举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。- 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
- 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的 是哪个类。
- 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
- import static组合的使用:调用指定类或接口下的静态的属性或方法
3.4.9 类的访问控制
- Java提供了访问权限修饰词,用于直观地反映出类、类的数据以及成员方法的封装程度,指明其可访问程度。访问控制权限分为不同等级,从最大权限到最小权限依次为:
public→protected→包访问权限(没有关键字)→private - 对于类的访问控制只提供了public(公共类)及包(默认类)两种权限,对于类成员的访问控制权限有以下几种:
1️⃣公有(public)可以被其他任何对象访问(前提是对类成员所在的类有可访向权限)。
2️⃣保护(protected):只可被同一类及其子类的对象访问。
3️⃣包访问权限:不加任何修饰符,默认访问权限,仅允许同一个包内的成员访问。
4️⃣私有(private): 只能被这个类本身方法访问,在类外不可见。 - 对于同类、同包及其子类情形下,访问权限修饰符表示的封装程度如表所示
访问权限
修饰符 | 同类 | 同包 | 子类 | 不同包之间的通用性 |
public | 是 | 是 | 是 | 是 |
protected | 是 | 是 | 是 | 否 |
default | 是 | 是 | 否 | 否 |
private | 是 | 否 | 否 | 否 |
- 一般而言,如没有特殊需要,数据成员采用默认即包访问权限为妥,当然开发中根据实际情况采用适当的访问权限方式。