Notes on Thinking in Java

本文深入探讨面向对象编程的核心概念,包括对象、类、继承、多态及访问控制。解析深克隆、别名现象与对象引用,对比==与equals的区别,详解数据初始化顺序、权限控制、复用策略及多态特性。适合初学者与进阶者巩固面向对象编程基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一章 对象导论
第二章 一切都是对象
前两章是从宏观来介绍面向对象编程相关的内容,挺有意思,可多看几遍。
笔记从第三章开始:

第三章 操作符

别名现象

赋值对象引用会发生什么
将一个对象赋值给另一个对象,实际上是将引用从一个地方复制到另一个地方。

若想保持两个对象彼此独立,不建议直接操作对象内的域。容易导致混乱,且违背了面向对象程序设计的原则。
解决方案:深克隆
https://blog.youkuaiyun.com/DeMonliuhui/article/details/54572908
https://blog.youkuaiyun.com/nishuishenhan/article/details/4693710
https://blog.youkuaiyun.com/qq_28081081/article/details/80455150

==和equals

1)对于==比较的是值是否相等

如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址

2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量,equals继承Object类,比较的是是否是同一个对象

如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

int x = 10;
int y = 10;
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(x == y); // 输出true
System.out.println(str1 == str2); // 输出false

String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1.equals(str2));//输出true
System.out.println(str1 == str2);//输出false

上述str1和str2都是在堆内存中创建了对象!new了

String s1 = "abc";
String s2 = "abc";
System.out.println(s1.equals(s2));//输出true
System.out.println(s1 == s2);//输出true

为什么第二个会是true呢?
涉及到了内存中的常量池,常量池属于方法区的一部分,当运行到s1创建对象时,如果常量池中没有,就在常量池中创建一个对象"abc",第二次创建的时候,就直接使用,所以两次创建的对象其实是同一个对象,它们的地址值相等。

第五章 初始化与清理

数据初始化顺序

类加载时:(静态只执行一次)

父类——静态变量
父类——静态初始化块
子类——静态变量
子类——静态初始化块
类创建时:(每次创建类执行)
父类——变量
父类——初始化块
父类——构造器
子类——变量
子类——初始化块
子类——构造器

第六章 访问权限控制

JAVA解释器运行过程(加载包过程)

首先,找出环境变量CLASSPATH,CLASSPATH包含一个或多个目录,用作查找.class文件的根目录。从根目录开始,解释器获取包的名称并将每个句点替换成反斜杠,以从CLASSPATH根中产生一个路径名称(于是,package foo.bar.baz会变成foo\bar\baz或foo/bar/baz或者其他;这一切取决于操作系统)。得到的路径会与CLASSPATH中的各个不同的项相连接,解释器就在这些目录中查找与你所要创建的类名称相关的.class文件。(解释器还会去查找某些涉及java解释器所在位置的标准目录。)

private构造器

构造器私有化,谁也无法创建该类的对象,别人该怎样使用这个类呢?

1、创建一个static方法,创建一个新的对象并返回一个对它的引用。如果想在返回引用前做一些额外的工作,或者记录到底创建了多少个对象,此种做法可行。

class Sundae {
  private Sundae() {}
  public static Sundae makeASundae() { 
    return new Sundae(); 
  }
}

2、单例模式singleton

class Soup2{
	private Soup2(){}
	private static Soup2 ps1=new Soup2();
	public static Soup2 access(){
		return ps1;
	}
}

Soup2类的对象是作为Soup2的一个static private 成员而创建的,所以有且仅有一个,而且除非是通过public方法access(),否则是无法访问到它的。

第七章 复用类

在组合和继承之间选择

组合:想在新类中使用现有类的功能而非是它的接口(has-a)有一个

继承:使用某个现有类,并开发它的特殊版本 (is-a)是一个
到底该用组合还使用继承?
问一问自己是否需要从新类向基类进行向上转型。
如果必须向上转型,则继承是必须的;但如果不需要,则应当好好考虑自己是否需要继承。

其它:private保留“更改底层实现”的权利。然后通过protected方法来控制类的继承者的访问权限

第八章 多态

多态:编译器一直不知道对象的类型,但是方法调用机制能找到正确的方法体,并加以调用。

1、只有非private方法才可以被覆盖
2、只有普通方法的调用可以使多态的
3、如果某个方法是静态的,它的行为就不具有多态性。(静态方法是与类,而并非单个的对象相关联的)
4、父类一个变量,子类一个同名变量不会覆盖父类的
Super sup=new Sub();
sup.field变量还是父类的,sup的普通方法是子类的

因为任何域访问操作都将由编译器解析,因此不是多态的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值