文章目录

  • 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 中的所有对象- -律 在内存的堆中分配空间,对象不再使用时,应该释放所占有的内存空间。

java 函数返回dto java 函数返回类 指针_this指针



  • 与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();
	}
}
  • 注意:
  1. 在源文件中使用import显式的导入指定包下的类或接口
  2. 声明在包的声明和类的声明之间。
  3. 如果需要导入多个类或接口,那么就并列显式多个import语句即可
    举例:可以使用java.util.*的方式,一次性导入util包下所有的类或接口。
  4. 如果导入的类或接口是java.lang包下的,或者是当前包下的,则可以省略此import语句。
  5. 如果在代码中使用不同包下的同名的类。那么就需要使用类的全类名的方式指明调用的 是哪个类。
  6. 如果已经导入java.a包下的类。那么如果需要使用a包的子包下的类的话,仍然需要导入。
  7. import static组合的使用:调用指定类或接口下的静态的属性或方法

3.4.9 类的访问控制

  • Java提供了访问权限修饰词,用于直观地反映出类、类的数据以及成员方法的封装程度,指明其可访问程度。访问控制权限分为不同等级,从最大权限到最小权限依次为:
    public→protected→包访问权限(没有关键字)→private
  • 对于类的访问控制只提供了public(公共类)及包(默认类)两种权限,对于类成员的访问控制权限有以下几种:
    1️⃣公有(public)可以被其他任何对象访问(前提是对类成员所在的类有可访向权限)。
    2️⃣保护(protected):只可被同一类及其子类的对象访问。
    3️⃣包访问权限:不加任何修饰符,默认访问权限,仅允许同一个包内的成员访问。
    4️⃣私有(private): 只能被这个类本身方法访问,在类外不可见。
  • 对于同类、同包及其子类情形下,访问权限修饰符表示的封装程度如表所示
    访问权限

修饰符

同类

同包

子类

不同包之间的通用性

public





protected





default





private





  • 一般而言,如没有特殊需要,数据成员采用默认即包访问权限为妥,当然开发中根据实际情况采用适当的访问权限方式。