《Java黑皮书基础篇第10版》 第9章【笔记】

第九章

9.1 引言

9.2 为对象定义类

类:

类可以储存同类型的对象,例如圆就是一个类

(ClassName: Circle)

对象:

创建对象的过程被称为实例化,一个对象有自己的数据域(字段),例如圆的数据域是半径

(ClassName: Circle - Circle Object: 01 - Data Fields: radius)

方法:

方法可以要求对象完成某个动作,例如求圆的周长和面积

构造方法:

调用构造方法可以创建一个新对象,设计构造方法是为了初始化动作:例如,初始化圆的数据域(半径)

UML(统一建模语言)类图:

数据域:dataFieldName: dataFieldType

构造方法:ClassName(parameterName: parameterType)

方法:methodName(parameterName: parameterType): returnType

9.3 示例:定义类和创建对象

面向对象编程中,main主类的唯一目的就是测试定义类(例如:圆类),这种其他类被称为主类的客户

Java编译器在编译**.java文件时,会生成一个主类.class文件和一个定义类.class**文件

可以创建若干个对象,并通过自定义的变量进行引用

对象有独立的数据域,但是可以使用相同的方法

可以通过对象的引用.数据域来访问对象的数据域,可以通过对象的引用.方法来调用对象的方法

9.4 使用构造方法构造对象

构造方法语法:

public ClassName() {
    
    
}

调用构造方法语法:

ClassName ObjectRefVar = new ClassName(arguments);

构造方法在使用new操作符创建对象的时候被调用(初始化对象)

当类中没有明确定义任何构造方法时,编译器会自动生成一个默认构造方法,它没有参数,因为也被称为无参构造方法

9.5 通过引用变量访问对象

新创建的对象在内存中被分配空间

9.5.1 引用变量和引用类型

本质上来说,类是一种引用类型(referencetype), 这意味着该类类型的变量都可以引用该类的一个实例,例如

Circle myCircle = new Circle();

引用变量myCircle中放的是一个Circle对象的引用

严格意义上讲,对象的引用变量和对象是不同的,但是这种差异是可以忽略的,因此可以简单地说,myCircle是一个Circle对象

9.5.2 访问对象的数据和方法

对象的数据和方法可以运用点操作符(.)通过对象的引用变量进行访问

引用对象数据域

objectRefVar.dataField

调用对象方法

objectRefVar.method(arguments)

匿名对象

//一个对象在创建之后不需要引用,这种对象称为匿名对象
System.out.println("Area is " + new Circle(5).getArea());

数据域radius称作实例变量(instance variable), 因为它依赖于某个具体的实例。

基于同样的原因,getArea方法称为实例方法(instance method), 因为只能在具体的实例上调用它。

调用对象上的实例方法的过程称为调用对象(calling object)。

Math类中,所有的方法都是静态方法,因此可以直接用类名调用,例如Math.pow()

但是对于实例方法而言,实例方法是非静态的,必须使用objectRefVar.method(arguments)的方式去调用

9.5.3 引用数据域和null值

数组是对象,String是类,类是一种引用类型

数据域的引用变量也可以是String引用类型的

9.5.4 基本类型变量和引用类型变量的区别

每个变量都代表一个存储值的内存位置

如图所示,对基本类型变量来说,对应内存所存储的值是基本类型值;对引用类型变量来说,对应内存所存储的值是一个引用,是对象的存储地址

在这里插入图片描述

如果所示,将一个变量赋值给另一个变量时,对基本类型变量而言,就是将一个变量的实际值赋给另一个变量;对引用类型变量而言,就是将一个变量的引用赋给另一个变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NxoJXnCT-1673786837441)(/Users/kevinwang/Library/Application Support/typora-user-images/image-20230112105115788.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iZhSd2Pr-1673786837442)(/Users/kevinwang/Library/Application Support/typora-user-images/image-20230112105123859.png)]

现在,c1以前引用的对象就会成为垃圾,会被Java运行系统自动回收

所以,如果不再需要每个对象,可以显式的给对象的引用变量赋值null。如 果该对象没有被任何引用变量所引用,Java虚拟机将自动回收它所占的空间。

9.6 使用Java库中的类

java.util.Date

java.util.Random

javafx.geometry.Point2D

9.7 静态变量、常量和方法

9.7.1 静态变量

对于实例变量(如Circle类中的radius),是绑定到某个特定实例的,每个实例都储存在不同的内存位置

对于静态变量(或称类变量),是所有实例共享的,储存在一个公共的内存地址

无static的字段就是实例变量,static字段就是静态变量

创建静态变量语法:

static variableType name;

创建静态变量例子:

static int numberOfObjects;

调用静态变量可以使用类名.静态变量名,例如

CircleWithStaticMembers.numberOfObjects

虽然可以使用实例变量名.静态变量名(但是最好不要这么写,因为静态变量并不属于实例变量,只是编译器可以自动转化为类名.静态变量名

c1.numberOfObjects
9.7.2 静态方法

静态方法不能访问类中的实例成员,无须创建类的实例就可以调用静态方法

静态方法内部,无法访问this变量,也无法访问实例字段,它只能访问静态字段

创建静态方法语法:

static variableType methodName() {
	return staticVariableName
}

例子:

static int getNumberObjects() {
    
    
	return numberOfObjects; 
}

调用静态方法使用类名.方法名(参数),例如

CircleWithStaticMembers.getNumberOfObjects()

最好通过类名去访问静态方法和静态变量,不要通过实例变量去访问静态变量和静态方法,否则会得到一个编译警告,编译器自动帮我们把实例变量改写成类名

通过类名只能访问静态方法和静态变量,不可以访问实例变量和实例方法

//最好不要这样
c1.getNumberOfObjects()

也可以使用

CircleWithStaticMembers.getNumberOfObjects

实例方法可以调用实例方法和静态方法,以及访问实例数据域或者静态数据域。

静态方法可以调用静态方法以及访问静态数据域。然而,静态方法不能调用实例方法或者访问实例数据域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jXh8DwP7-1673786837443)(/Users/kevinwang/Library/Application Support/typora-user-images/image-20230114232050049.png)]

9.7.3 常量

常量应该使用final static修饰,是被该类当中所有的对象共享的

声明常量语法举例

final static double PI = 3.14159265

9.8 可见性修饰符

9.8.1 public修饰符

可以在类、方法和数据域前使用public修饰符,表示它们可以被任何其他的类访问

如果没有使用可见性修饰符 ,那么则默认类 、方法和数据域是可以被同一个包中的任何一个类访问的。这称作包私有(package private)或包内访问(package access)

**包可以用来组织类。**为了完成这个目标,需要在程序中首先出现下面这行语句,在这行语句之前不能有注释也不能有空白:

package packageName;

如果定义类时没有声明包,就表示把它放在默认包中。Java建议最好将类放入包中,而不要使用默认包。

9.8.2 private修饰符

private修饰符限定方法和数据域只能在它自己的类中被访问。

在同一个包内,不管有没有public修饰符,都可以在不同的类中,实现数据域和方法的访问;

在不同的包中,只有显式的标识public修饰符的字段和方法,才可以被另一个类访问

在同一个包内,不管有没有public修饰符,类和类之间都可以互相访问

在不同的包中,只有显式的标识public修饰符类,才可以被另一个类访问

修饰符private只能应用在类的成员上。修饰符public可以应用在类或类的成员上。在局部变量上使用修饰符public和private都会导致编译错误。

9.9数据域封装

为了避免对数据域的直接修改,应该使用private修饰符将数据域声明为私有的,这称为数据域封装

为了能够访问私有数据域,可以提供一个get方法返回数据域的值,也可以提供一个set方法给数据域设置新值。get方法也被称为访问器(accessor), 而set方法称为修改器(mutator)。

get方法签名:

public returnType getPropertyName()

//如果返回值类型是boolean型,习惯上如下定义get方法:
public boolean isPropertyName()

set方法签名:

public void setPropertyName(dataType propertyValue)

9.10 向方法传递对象参数

传递基本数据类型参数时,传递的是实参的值,可以认为,方法复制了参数,双方各自的后续修改,互不影响

传递引用类型的参数时,传递的是对象的引用,方法内部和对象引用变量都指向一个对象,所以修改其中一个,就会牵一发而动全身

在这里插入图片描述

9.11 对象数组

数组既可以储存基本类型值,也可以储存对象

当使用new操作符创建对象数组后 ,这个数组中的每个元素都是默认值为null的对象的引用变量

如果引用变量是null,访问其字段或引用其方法会导致空指针异常NPE

9.12 不可变对象和类

要使一个类成为不可变的,它必须满足下面的要求:

​ ·所有数据域都是私有的。

​ ·没有修改器方法。

​ ·没有一个返回指向可变数据域的引用的访问器方法。

9.13 变置的作用域

—个类的实例变量和静态变量称为类变量(class’s variables)或数据域(data field)。无论在何处声明,类变量的作用域都是整个类。

方法内部定义的变量称为局部变量。

类的变量和方法可以在类中以任意顺序出现,只有一种情况例外,如下图

在这里插入图片描述

类变量只能声明一次,如果一个局部变量和一个类变量具有相同的名字,那么局部变量优先,而同名的类变量将被隐藏

9.14 this引用

this关键字有两个作用

使用this引用隐藏数据域

当类变量(或数据域)与局部变量命名冲突时,会优先考虑局部变量,同名的类变量会被隐藏

而在set方法中,很容易定义一个与类变量(或数据域)同名的局部变量,此时类变量就会被隐藏,此时如果想给类变量赋值,就可以使用this定位到相应的对象

在这里插入图片描述

使用this调用构造方法

为了易于代码的阅读和维护,如果一个类有多个构造方法,应该尽可能在参数较少的构造方法中使用this,来调用参数较多的构造方法(要注意,java要求,this应该出现在构造方法中其他可执行语句之前)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_40020256/article/details/128697642
今日推荐