- 识别类的简单规则是在分析问题的过程中寻找名次,而方法对应着动词
- 类之间最常见的三种关系:
- 依赖关系:即"uses-a"的关系。如果一个类的方法操作另一个类的对象(方法参数),也就是说这个类依赖于另一个类。应该尽可能地将相互依赖的类减至最少,即让类之间的耦合度更小
- 聚合关系:即"has-a"的关系。意为着一个类中包含另一个类的对象(实例域)
- 继承关系:即"is-a"的关系。
- 表达类关系的UML符号:
- new 操作符的返回值是一个引用(对象的地址),new String()除外???
- 局部变量不会初始化为空(局部变量若不初始化就试图引用,则会报错)。只有是类的实例域(对象变量)才会被初始化为null
private static int[] a;
public static void main(String[] args){
System.out.println(a == null);//true
}
- 日历类:LocalDate
System.out.println(LocalDate.now());//2018-11-29
LocalDate ld = LocalDate.of(2018, 1, 1);//构造一个指定的日期
LocalDate ld2 = ld.plusDays(1000);//在日期ld的基础上增加1000天
System.out.println(ld2);//2020-09-27
- 更改器方法和访问器方法:只访问对象而不修改对象的方法称为访问器方法
- 不要编写返回可变引用对象的访问器方法,因为这样在类外部也可以完成对类内部私有实例域的改变。而应该返回该可变数据域的拷贝,应使用clone方法(该类需事先Cloneable接口并重写clone())
public class Test {
public static void main(String[] args){
Employee e = new Employee();
int[] res = e.getArray();
System.out.println(Arrays.toString(res));//[1,2,3]
res[0] = 4;
System.out.println(Arrays.toString(e.getArray()));//[4,2,3]
}
}
class Employee{
private int[] array = {1,2,3};
public int[] getArray() {
return array;
}
}
public class Test {
public static void main(String[] args){
Employee e = new Employee();
int[] res = e.getArray();
System.out.println(Arrays.toString(res));//[1,2,3]
res[0] = 4;
System.out.println(Arrays.toString(e.getArray()));//[1,2,3]
}
}
class Employee{
private int[] array = {1,2,3};
public int[] getArray() {
return array.clone();//返回array的一个副本(在堆中又新建了一个与array中元素一样的数组并返回)
}
}
- final实例域必须在定义时初始化或者在构造器中初始化后才能被使用
- 而其他类型实例域都是在定义的时候,类已经给了初始值
- 静态常量(static final)一般被设置为public。因为final限制了它不能被Java方法修改,所以设置为public更方便在类外使用类名.变量名直接调用变量
- 一个典型的静态常量System.out:
public final static PrintStream out = null;
看到这,为什么null还能调用println方法呢?因为在System.class中有一个setOut方法,它调用了一个本地方法setOut0(),而本地方法是不受Java语法的限制的
public static void setOut(PrintStream out) {
checkIO();
setOut0(out);
}
private static native void setOut0(PrintStream out);
那么setOut方法又是什么时候被调用改的呢?我猜测是被虚拟机内部调用的(这里还是不太理解,只知道有这么个流程)
System.out.println(System.out);//java.io.PrintStream@7852e922
将静态常量System.out打印出来,我们发现它并不是null,由此可以肯定out已经被修改了
- 静态方法不能访问实例域,只能访问静态域(因为静态方法不能操作对象);实例方法既可以访问实例域也可以访问静态域
- 工厂方法:使用类的某个static final方法返回类的实例或者其子类的实例
NumberFormat cf = NumberFormat.getCurrencyInstance();
NumberFormat pf = NumberFormat.getPercentInstance();
double x = 0.1;
System.out.println(cf.format(x));//¥0.10
System.out.println(pf.format(x));//10%
- 一个Java文件中可以有多个类,但只能有一个public类;每一个类中都可以有一个static void main(),方便用于单元测试
- Java中总是采用按值(对象变量传递的是其指向对象所在的地址)传递,也就是说方法得到的是所有参数值的一个拷贝,而不是直接引用。代码佐证如下
public class Test {
public static void main(String[] args){
Employee e1 = new Employee("e1");
Employee e2 = new Employee("e2");
Employee.swap(e1, e2);
System.out.println(e1.name);
System.out.println(e2.name);
}
}
class Employee{
public String name;
public Employee(String n) {
name = n;
}
public static void swap(Employee x,Employee y) {
Employee tmp = x;
x = y;
y = tmp;
}
}
如果是引用(x与e1就是同一个对象变量,y与e2也是同一个对象变量)的话,因此使x重新指向另一个对象也就是使e1重新指向另一个对象,y与e2同理。输出的应该就是e2,e1
如果是拷贝的话(x与e1是两个不同的对象变量,但都指向同一个对象e1;y与e2也是两个不同的对象变量,也都指向同一个对象e2),使x重新指向另一个对象并不会对e1有任何影响,y与e2同理。因此输出的应该是e1,e2
而最后结果输出确实是e1,e2.因此可以证明Java中参数传递是拷贝传递(按值传递)而不是引用传递
以上建议画图理解
- 方法签名:方法名 + 参数类型列表
- 类会自动对域进行初始化(无论是基本数据类型还是非基本数据类型),不会对局部变量进程初始化(无论是基本数据类型还是非基本数据类型)
- 仅当类没有提供任何构造器的时候,系统才会提供一个默认的构造器
- Java如果有final实例域,必须在类外对其完成初始化!!!
- Java对实例域的初始化顺序:static实例域 ---> 按从上至下对非static实例域初始化(如果初始化实例域时需要调用类的某个方法,那么就直接调用) --->调用类的构造器方法。代码佐证如下:
public class Test {
public static void main(String[] args){
Employee e1 = new Employee();
System.out.println(e1.name);
}
}
class Employee{
public int t = 10;
public final int b = t;
public String name = setName();
public static int a = 5;
public Employee() {
System.out.println("hello");
}
public String setName() {
System.out.println(a);
System.out.println(b);
return "s";
}
}
输出结果为:
5
10
hello
s
static实例域会被最先初始化,但是static函数并不会被自动调用,只有当被类调用的时候才起作用。代码佐证如下:
public class Test {
public static void main(String[] args){
Employee e1 = new Employee();
System.out.println(e1.name);
}
}
class Employee{
public int t = 10;
public final int b = t;
public String name = "sc";
public static int a = 5;
public Employee() {
System.out.println("hello");
}
public static String setName() {
System.out.println(a);
// System.out.println(b);
return "s";
}
}
输出结果:
hello
sc
- Java可以通过this关键字在构造器中调用另一个构造器
- 静态初始化块: static{} 对象初始化块:{}
- 可以为任何一个类添加finalize方法。finalize方法将在垃圾回收器清除对象之前调用。在实际应用中,不要依赖于使用finalize方法回收任何短缺的资源,这是因为很难知道这个方法什么时候被调用
- 使用包的主要原因是确保类名的唯一性
- 标记为public的部分可以被任意的类使用;标记为private的部分只能被定义它们的类使用。如果没有指定public或private,这个部分(类、方法或变量)可以被同一个包中的所有方法访问