三个重要概念:java
封装app
继承dom
多态ui
类之间的常见关系有:this
依赖(uses-a):一个类的方法操纵另外一个类的对象lua
聚合(has-a):一个类的对象包含另外一个类的对象spa
继承(is-a):一个类是另外一个类的拓展(子集)设计
3d
在设计类时,应尽量将相互依赖的类减至最少,用软件工程的术语来讲,就是让类的之间的耦合度最小。指针
一个对象变量(引用)并无实际包含一个对象,而仅仅存放了这个对象实体的内存地址,换句话说,任何对象变量的值都是对存储在堆(heap)中的一个对象的引用。能够将 Java 的对象变量看做 C++ 的对象指针(而不是 C++ 的引用),这个值能够是 null ,代表目前没有指向任何对象。
对引用的值进行拷贝,结果以下:
一个源文件只能有一个公有类,但能够有任意数目的非公有类,源文件名必须与公有类的名字相同,不然没法编译。
关于多个源文件的编译顺序,“能够认为 Java 编译器内置了 make 功能。”
不能对一个已经存在的对象调用构造器
若是没有编写构造器,默认的无参数构造器会将实例域设置为默认值
一旦编写了构造器,就再也不提供默认的无参数构造器
隐式参数是出如今实例方法名前的类对象,也就是方法调用的目标或接受者,能够在方法内部用 this 表示,与之对应,列在方法声明中的参数就属于显式参数。
不要编写返回引用可变对象的访问器方法,由于对这个引用进行操做会改变原有的实例。若是须要返回一个可变数据域的拷贝,应该使用 clone 方法。
一个类的方法能够访问这个类的私有特性,即全部对象的私有数据,而不局限于调用它的单一对象的私有数据。
方法名以及参数类型(不包括返回类型)构成了方法的签名(signature)。若是多个方法有相同的名字、不一样的参数类型或顺序,便产生了重载(overload),编译器经过用各个方法给出的参数类型,与特定方法调用所使用的值类型进行匹配,挑选出相应的方法。
用 final 修饰的实例域必须在构建对象时进行初始化,在后面的操做中不能再对它进行修改,大都应用于基本(primitive)类型域,或不可变(immutable)类的域(该类中的每一个方法都不会改变其对象)。
对可变的类使用 final 修饰符可能会难以理清关系,例如:
public class Employee { private final StringBuilder evaluations; // ... Employee() { evaluations = new StringBuilder(); // evaluations 不可引用其余 StringBuilder 对象,但能够对当前对象的状态进行更改: evaluations.append(str); // ... } }
在绝大多数面向对象语言中,静态域被称为类域,由这个类的全部对象共享。
静态方法是一种没有隐式参数的方法,用类名进行调用(不提倡用其对象的引用),用于如下状况:
一个方法只须要访问类的静态域
工厂方法(factory method)
main 方法
按引用调用(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; } // ... }
在一个类的声明中,能够包含多个代码块,这些块会在构造对象时执行,运行顺序先于构造器。
构建一个对象实例时,具体的处理步骤是:
按照类声明中的次序,依次执行全部域初始化语句和初始化块
若是构造器第一行调用了第二个构造器,执行第二个构造器主体
执行这个构造器主体
在初始化块以前使用 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,则这个部分能够被同一个包中的全部方法访问(默认访问权限)。对类来讲,这种设计有必定的方便性,但对变量来讲并不合适,有时会忘记加上修饰符,从而破坏封装性。所以,最好记得在声明变量时对访问权限做出显式标记。
对数据初始化
尽可能用类替代多个基本类型的使用
get 方法和 set 方法并不是必需
将职责过多的类进行分解
名字要体现职责
优先使用不可变的类