学习笔记之《Java核心技术卷I》---- 第四章 对象与类

  • 识别类的简单规则是在分析问题的过程中寻找名次,而方法对应着动词
  • 类之间最常见的三种关系:
  1. 依赖关系:即"uses-a"的关系。如果一个类的方法操作另一个类的对象(方法参数),也就是说这个类依赖于另一个类。应该尽可能地将相互依赖的类减至最少,即让类之间的耦合度更小
  2. 聚合关系:即"has-a"的关系。意为着一个类中包含另一个类的对象(实例域)
  3. 继承关系:即"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,这个部分(类、方法或变量)可以被同一个包中的所有方法访问
  •  

猜你喜欢

转载自blog.csdn.net/smart_ferry/article/details/84639110