《Head First Java》读书笔记(壹)

基本概念

① Java是面向对象的语言,所有东西都包含在类中

源文件的扩展名为.java,编译后成为类文件,扩展名为.class真正被执行的是类

③ 执行程序就是:Java虚拟机(JVM)去加载这个类,开始执行他的main(),一直运行到main中所有代码结束为止
 

【类与对象】

① 一个类可以说是由实例变量( instance variable )和方法( method )组成的

② Java是面相对象的,因此没有全局的变量和方法;其实,声明为publicstaticfinal后,基本上就获得global的效果了

 

primitive主数据类型和引用

① 变量有两种:primitive主数据类型引用

② primitive主数据类型(“就是”) 的变量值就是该值的字节表示的

③ 引用(“管理者”) 变量值代表的是位于堆的对象的存取方法

④ 如下表

primitive主数据类型位数值域
boolean(由Java虚拟机决定)true或false
char2字节0~65535
byte1字节-128~127
short2字节-32768~32767
int4字节-2147483648~2147483647
long8字节-很大~很大
float4字节范围规模可变
double8字节范围规模可变

⑤ 需要注意的是,诸如32.5默认为double类型,声明float的正确姿势是:float num = 32.5f结尾的" f "必不可少

溢位(大杯的内容放进小杯)demo : byte num = 150

  但反过来可以,因为小值可以隐含展开(implicit widening)后转入大杯中

⑦ 引用(reference)绝不是对象本身,也不是个容器;对象引用变量保存的是存取对象的方法,可以理解为地址,或者指针。

 这就是“管理者”的思想

⑧ 对于同一个Java虚拟机来说,所有的引用都具有相同的大小;其被声明的类型的作用是“检查”而非初始化其大小

 

实例变量与方法

① Java是通过值传递(pass by value)的,也就是传递的都是拷贝

return时也存在隐含展开现象

③ 一个典型的封装(Encapsulation)操作:

  将实例变量声明为private,将getter与setter声明为public(也就是说,别人不能直接改变实例变量的值,必须通过某些方法对其进行修改等操作

  这样"多此一举"有什么好处呢?

  安全性可维护性

  比如,Person类有一个age实例变量,强迫其他程序必须通过setter来修改这个值。这样,当这个值非常不合理时,比如设置为5000,setter方法可以对其进行修改或者直接抛出异常

  也许某些setter,getter什么事情也没做,只是把值传给变量而已。但从防患未然和可维护的角度出发,这种习惯十分有必要

实例变量(类中的变量)永远会有默认值局部变量(方法中使用的变量)没有默认值

⑤ 关于" == "的意义老生常谈,不再赘述;这里提一个小tip:

  用 == 直接比较两个primitive主数据类型是否相等(字节组合相等那么数据当然相等)

  用 == 比较两个引用是否指向同一个对象

 

API

APIApplication Programming Interface应用程序编程接口

② 运行Java程序时,虚拟机装载程序的class文件所使用的Java API class文件。

所有被装载的class文件(包括从应用程序中和从Java API中提取的)和所有已经装载的动态库(包含本地方法)共同组成了在Java虚拟机上运行的整个程序。

③ 特点:无需访问源码,或理解内部工作机制的细节

④ 我们讲使用API,实际上是使用已经写好的类,而类是被包装在包中的package机制)。

  因此,使用API类时,必须知道它被放在哪个包中,并且使用其全名包名+类名

  可是,我们平常使用API时也不是写它的全名啊?这是因为有import

⑤ 我们必须理解import的本质。import是在加载该类吗?

  并不是

  这是一个误区,认为import是在将类加载到内存中。这一点java的import与C的include不同:

  import的作用是帮你省下每个类前面的包的名称,仅此而已

  当忘记import时,报错是因为缺少该包的导入吗?不全是。报错的真正原因是由于使用的类不是包含包名的全称,编译时无法准确找到这个类并加载到内存中。也就是说,我们可以这样:

java.util.List<Integer> a = new java.util.ArrayList<>();

等同于:

import java.util.List;
import java.util.ArrayList;
List<Integer> a = new ArrayList<Integer>();

java.lang不需要指定全名,因此也不需要import

 

继承与多态

IS-A测试。如果能通过IS-A测试(“是一个”)那么便存在继承关系,且可以使用多态

demo: Dog is a Animal

② 子类会继承父类所有的public类型的实例变量和方法,但不会继承父类所有private类型的实例变量和方法

③ 继承时,方法可以被覆盖但实例变量不能被覆盖

④ 从子类调用父类的方法可以使用super关键字:super.method();

④ 调用某个对象的方法时,Java虚拟机会首先从该对象的类开始寻找该方法;若没有找到,则一直向父类寻找直到找到该方法。也就是说,会使用最近的方法

⑤ 一个例子看懂多态:

Animal mydog = new Dog();

不仅引用类型可以是实际对象类型的父类参数返回类型也可以体现多态

笔者的思考
我们给primitive主数据类型声明类型,比如 int a,目的是什么?
是为了根据类型分配内存空间(容器的大小),从而保证内存空间的充分高效利用。
 
可是,对于引用,它类似指针,其大小都是相同的,这是给其声明类型,比如Animal a,又有什么用呢?
是"检查"。Animal类型的引用只能指向Animal类型或者其子类类型的对象(is A 测试同样适用)。从这个角度,我们能更加深入的理解多态。

⑥ 有三种方法可以防止某个类被做成子类:

  1. 存取控制。虽然不能将一个类标记为private,但可以不标记为public。这样非公有的类只能被同一个包的类作出子类;

  2. 使用final修饰符。这表示它是继承树的末端,不能被继承;

  3. 让类只拥有private的构造程序(constructor)

⑦ 用final标记某个特定的方法,可以防止该方法被覆盖;而将整个类标记为final,该类所有的方法都无法被继承,毕竟该类已经无法被继承了。

⑧ 区分覆盖override)和重载overload

覆盖是指覆盖(重写)父类的方法

覆盖的规则:

  1. 参数必须要一样;返回类型必须要兼容。解释:父类的方法返回类型为long,重写的方法返回类型可以为int

  2. 不能降低方法的存取权限。解释:存取权限必须相同,或者更开放,比如,你不能覆盖掉一个公有的方法并将它标记为私有

重载也被称为过载,只是刚好两个方法的名称相同,参数不同(与多态完全是两码事)

重载的规则:

  1. 重载的关键是参数不同,返回类型可以任意改变。解释:仅仅返回类型不同,方法名称和参数相同,是无法通过编译的

  2. 可以更改存取权限(重载方法彼此是相对独立的)

 
 

【abstract 抽象类和抽象方法】

① 如果你不想某个类被初始化,就以abstract将这个类标记为抽象类

编译器不会允许初始化抽象类,也就是说,无法new出一个对象,但可以用它的名字创建引用。比如Animal通常被声明为抽象类(abstract):

Animal pet = new Animal();			// (✘)抽象类无法被初始化,这没有意义,也不被编译器允许
Animal mydog = new Dog();			// (✔)可以作为引用的类型;这是多态的体现:Dog is a Animal
Animal[] animals = new Animal[5]	// (✔)这是可以的,Animal只是声明为数组类型,这是允许的,只是数组内部的成员必须是具体的类(Dog、Cat...)

③ 除了类之外,也可以将方法标记为abstract

抽象的类代表此类必须要被extend过抽象的方法代表此方法必须要被覆盖过

解释:抽象的方法没有实体内容(声明抽象方法后直接分号结束),因此它必须被覆盖。

④ 抽象的类中可以带有抽象和非抽象的方法

如果类带有抽象方法,则此类必定被标为抽象

可以这样理解:如果一个类带有抽象方法而这个类本身没有被标识为abstract,那么这个类被实体化后,便有机会调用这个抽象方法,这是危险且不被允许的。

⑥ 抽象方法为何存在?多态

⑦ 在继承树结构下的第一个具体类必须要实现出所有的抽象方法,也就是说,写出它们的内容

Java中所有的类都是Object(java.lang.Object)直接或间接的子类

编译器是根据引用类型来判断有哪些方法可以调用,而不是根据这个对象实际的类型

 

【接口与多态】

① 当一个父类A被两个类(B, C)继承时,且这两个子类都覆盖(重写)了父类的某一个方法,接着又有一个子类(D)多继承了这两个类

——此时问题浮现出来:D类new出的对象,在调用这个方法时,该运行哪一个版本呢?

   这就是多重继承机制的 致命方块 (或者称为 致命菱形

② Java不允许多重继承,而使用接口interface);

③ 接口是一个100%的纯抽象类;而且接口的方法自带public和abstract的意义

我们可以将其标识出来,也可以不这麽做;

④ 接口虽然不是真正的继承extends)而是实现implements),但仍能通过" IS A “测试,即” 是一个 "

⑤ 接口虽然不是一个真正意义上的父类,当仍可使用 多态性(这恰恰是我们使用接口的目的);

也就是说,引用类型参数返回值都可以是接口。

 

 

 

 
 

 

 

 

 

 

 

 

 

 

 
☀ 《Head First Java》Kathy Sierra & Bert Bates

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值