Core Java 笔记(三)- 对象与类

对象与类

 

三个重要概念:

  • 封装

  • 继承

  • 多态

类之间的常见关系有:

  • 依赖(uses-a):一个类的方法操纵另一个类的对象

  • 聚合(has-a):一个类的对象包含另一个类的对象

  • 继承(is-a):一个类是另一个类的拓展(子集)

表达类关系的统一建模语言符号:

在设计类时,应尽可能将相互依赖的类减至最少,用软件工程的术语来说,就是让类的之间的耦合度最小

 

区分对象引用和对象实体

一个对象变量(引用)并没有实际包含一个对象,而仅仅存放了这个对象实体的内存地址,换句话说,任何对象变量的值都是对存储在堆(heap)中的一个对象的引用。可以将 Java 的对象变量看作 C++ 的对象指针(而不是 C++ 的引用),这个值可以是 null ,表明目前没有指向任何对象。

对引用的值进行拷贝,结果如下:

 

一、自定义类

 

一个源文件只能有一个公有类,但可以有任意数目的非公有类,源文件名必须与公有类的名字相同,否则无法编译。

关于多个源文件的编译顺序,“可以认为 Java 编译器内置了 make 功能。”

 

构造器
  • 总是伴随着 new 操作被调用

  • 不能对一个已经存在的对象调用构造器

  • 如果没有编写构造器,默认的无参数构造器会将实例域设置为默认值

  • 一旦编写了构造器,就不再提供默认的无参数构造器

  • 可以把构造器的访问权限设为 private,这样就无法在外部用 new 来创建实例,Math 类就是这么做的

 

方法

隐式参数是出现在实例方法名前的类对象,也就是方法调用的目标或接受者,可以在方法内部用 this 表示,与之对应,列在方法声明中的参数就属于显式参数。

不要编写返回引用可变对象的访问器方法,因为对这个引用进行操作会改变原有的实例。如果需要返回一个可变数据域的拷贝,应该使用 clone 方法。

一个类的方法可以访问这个类的私有特性,即所有对象的私有数据,而不局限于调用它的单一对象的私有数据。

 

重载

方法名以及参数类型(不包括返回类型)构成了方法的签名(signature)。如果多个方法有相同的名字、不同的参数类型或顺序,便产生了重载(overload),编译器通过用各个方法给出的参数类型,与特定方法调用所使用的值类型进行匹配,挑选出相应的方法。 

 

final

用 final 修饰的实例域必须在构建对象时进行初始化,在后面的操作中不能再对它进行修改,大都应用于基本(primitive)类型域,或不可变(immutable)类的域(该类中的每个方法都不会改变其对象)。

对可变的类使用 final 修饰符可能会难以理清关系,例如:

public class Employee {
    private final StringBuilder evaluations;
    // ... 
    Employee() {
        evaluations = new StringBuilder(); 
      // evaluations 不可引用其他 StringBuilder 对象,但可以对当前对象的状态进行更改: evaluations.append(str);  
        // ...
    }
}

 

static

在绝大多数面向对象语言中,静态域被称为类域,由这个类的所有对象共享。

静态方法是一种没有隐式参数的方法,用类名进行调用(不提倡用其对象的引用),用于以下情况:

  • 一个方法不需要访问对象状态,所需参数皆显式提供

  • 一个方法只需要访问类的静态域

  • 工厂方法(factory method)

  • main 方法

  • aa

 

二、按值调用

 

  • 按值调用(call by value):方法接收的是调用者提供的值

  • 按引用调用(call by reference):方法接收的是调用者提供的变量地址

 

Java 总是按值调用,方法得到的是参数值的拷贝,不能修改传递参数变量的内容。为了说明这个问题,我们先做一个小实验:

public static void swap(Employee x, Employee y) {
    Employee temp = x;
    x = y;
    y = temp;
}
Employee a = new Employee("Alice", ...);
Employee b = new Employee("Bob", ...);
swap(a, b);
// x -> Bob, y -> Alice, a -> Alice, b -> Bob 

下面两幅图能很好地分清“不可以修改变量”和“可以修改引用指向的对象”之间的不同:

 

 总之,一个方法

  • 不能修改一个基础数据类型的参数

  • 可以改变一个对象参数的状态

  • 不能让对象参数引用一个新的对象

 

三、构造对象

 

初始化

必须明确地初始化方法中的局部变量,但如果没有初始化类中的域,将会被自动初始化为默认值(0 / false / null)。

显式的域初始化方法:

  • 定义实例域时直接赋值

  • 用 this 关键字调用另一个构造器(节省代码)

  • 初始化块

class Person {
    private int age;
    private boolean sex;
    private String name;
    private double asset;

    // initialization block
    {
        asset = 0;
    }

    // ...
}

在一个类的声明中,可以包含多个代码块,这些块会在构造对象时执行,运行顺序先于构造器。

构建一个对象实例时,具体的处理步骤是:

  1. 所有数据域初始化为默认值

  2. 按照类声明中的次序,依次执行所有域初始化语句和初始化块

  3. 如果构造器第一行调用了第二个构造器,执行第二个构造器主体

  4. 执行这个构造器主体

 

静态初始化

在初始化块之前使用 static 关键字可以对静态域进行初始化,适用于无法准确知道赋值内容的时候:

// static initialization block
static {
    Random generator = new Random();
    nextId = generator.nextInt(10000);
}

类第一次加载时就会进行静态域的初始化,所有的静态域初始化语句、静态初始化块都将按照定义的顺序进行。

 

析构

Java 有自动的垃圾回收器(GC),不需要人工回收内存,因此 Java 不支持析构器。不过,如果对象使用了内存之外的其他资源(比如文件),那么当资源不再需要时,应该将其回收和再用。可以在类中添加 finalize 方法,它会在 GC 清除对象之前调用以回收资源。

由于难以预料 GC 什么时候会清除对象,所以不要依赖 finalize 方法来回收短缺的资源。想在某个资源使用后立刻关闭,可以在对象的方法中调用一个相应的 close 方法。

 

四、包

 

名字相同的类放置于不同的包中,就不会产生冲突。借助包可以方便组织自己的代码,并与别人提供的代码库分开管理。标准的 Java 包具有一个层次结构,它们都处于 java 和 javax 包层次中。不过从编译器的角度来看,嵌套的包之间没有任何关系,每一个包的类集合都是独立的。

 

导入

一个类可以使用所属包中的所有类,以及导入的其他包中的公有类。 import 语句可以导入一个特定的类或者整个包(用 *),不存在一条语句导入多个包的情况。Java 中的 package  和 import 语句类似于 C++ 中的 namespace 和 using 指令。

前面提到过静态导入,结合 static 关键字并在类名后再接上星号,就可以使用指定类的静态方法和静态域,不必再加类名前缀。例如:

import static java.lang.System.*;
// ...
    out.println("good good study");
    exit(0);
// ...

 

作用域

如果一个类、方法或变量没有指定为 private 或 public,则这个部分可以被同一个包中的所有方法访问(默认访问权限)。对类来说,这种设计有一定的方便性,但对变量来说并不合适,有时会忘记加上修饰符,从而破坏封装性。因此,最好记得在声明变量时对访问权限作出显式标记

 

五、类设计技巧

 

  • 一定要保证数据私有

  • 一定要对数据初始化

  • 尽量用其他类替代多个相关的基本类型的使用

  • 不是所有的域都需要独立的访问器和更改器

  • 将职责过多的类进行分解

  • 名字要体现职责

  • 优先使用不可变的类

  • 迪米特法则(LoD,一个对象应当对其他对象有尽可能少的了解,“talk only to your immediate friends”

 

转载于:https://www.cnblogs.com/zzzt20/p/11441017.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值