欢迎

How more than you show,speak less than you know.

读书笔记:HeadFirst Java (上)

《读书笔记:HeadFirst Java (上)》

重新学!目的是系统的过一遍,对Java的整个体系做一个了解。只写自己模糊,感觉需要记下的内容。

格式备注:


目录就是书的副标题(正式标题实在是太弱智了)。

日后有补充和纠错,用红色标注

*号粗体表示扩展和解释。如果没写,用绿色背景。

编写日志中绿色部分是需要随时再补充的。

每一章的标题后,会标记本章需要日后补充的点的数目。若日后补充过,则更新数字。

注:用斜体

尽量不要写太多的注,因为会使文章不清晰凌乱。

*扩展内容四级标题

大标题前空一格


编写日志:


2018.7.06 :记下了基本概念对象这一章的笔记,书已经看过一半了,从头开始写主要是为了连贯。

2018.7.07 :写了类和对象这一章,同时搞了大约3h的锚点。出了点问题。补充了基本概念一章的扩充内容。(需要再补充动态绑定的问题。)

2018.7.13:写了第三章的笔记。

2018.7.21:写了第四章笔记,并补充第三章primitive的主数据类型(因为总以为string也是)。

2018.8.04:修改了格式备注,字体颜色修改为字体背景。不知道是否会影响其他浏览器或移动设备。完成第五六章内容

2018.8.06:修改了文章格式,完成第七章内容。修改以前几章的小标题(这样看着更清晰不然知识点太散了)。目录显示四级标题。加了注的格式规则。*扩展内容改为四级标题(随时改回来)大标题前加一个回车

2018.8.10:完成十章的内容就换一本写。草草完成第八九十章内容。


第一章 基本概念(需补充点:1)


Java的工作方式

  • ↓源代码(其中一个类带有用于启动程序的main方法)
    ↓编译器(运行源代码、检查错误)
    ↓输出(编译器产生的字节码)
    ↓JVM(java虚拟机可以读取和执行字节码)

我需要做的事:

  • ↓编程
    ↓javac来编译.java文件,并生成.class文件(由字节码组成)
    ↓JVM运行.class文件(将字节码转换成平台能够理解的形式运行)
    Java介绍:5.0版本有3500个类,当然早期版本类更少。

Java的版本

本书发行是Java版本是5.0,现在已经到了10

Java的版本变化:上网查吧(版本号很跳跃,并没有java3,4)

 

编译器和虚拟机的功能

编译器用来生成可供JVM执行的二进制代码。Java不是直译语言直译语言是什么?),所以需要编译器来编译,同时检查一些的错误,Java是个强类型语言(什么是强类型语言?),编译器会检查一些关键的类型安全以及存取权限的安全问题,如调用了private方法。但同时编译器也会放水,比如错误类型数据放入了数组,但这是为了容许动态绑定功能(什么是动态绑定?),所以编译器只能确保一定不该错的错误。

而JVM负责运行二进制代码,也就是说如果你能自己写出二进制代码,可以不用编译器,直接在JVM运行。其他的功能有待补充。(书中提到了“jvm可以确保不会有人在执行前修改二进制代码”?)

:wiki的译文为解释型语言Interpreted language)。

解释型语言是一种编程语言。这种类型的编程语言,会将代码一句一句直接运行,不需要像编译语言(Compiled language)一样,经过编译器先行编译为机器码,之后再运行。这种编程语言需要利用解释器,在运行期,动态将代码逐句解释(interpret)为机器码,或是已经预先编译为机器码的的子程序,之后再运行。

理论上,任何编程语言都可以是编译式,或解释型的。它们之间的区别,仅与程序的应用有关。许多编程语言同时采用编译器与解释器来实现,其中包括Lisp,Pascal,C,BASIC 与 Python。JAVA及C#采用混合方式,先将代码编译为bytecode,在运行时再进行解释。

LISP,Perl,Python,Ruby,JavaScript,PHP,R为解释型语言。

强弱类型(Strong and weak typing)表示在计算机科学以及程序设计中,经常把编程语言的类型系统分为强类型(英语:strongly typed)和弱类型(英语:weakly typed (loosely typed))两种。这两个术语并没有非常明确的定义,但主要用以描述编程语言对于混入不同数据类型的值进行运算时的处理方式。强类型的语言遇到函数引数类型和实际调用类型不匹配的情况经常会直接出错或者编译失败;而弱类型的语言常常会实行隐式转换,或者产生难以意料的结果。这对术语在短短的计算机历史中,早已含括了更多的意义,而且时常很难知道写的人究竟要表达哪个意思。

“强类型”隐含着编程语言对容许混合情况出现加上了严格的限制,以避免代码以无效的数据使用方式编译或运行。例如,整数除法运算不可用于字符串;链表上的运算步骤不可用于数字。

摘自CSDN:深入理解C++的动态绑定和静态绑定

静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。

对象的静态类型:对象在声明时采用的类型。是在编译期确定的。
对象的动态类型:目前所指对象的类型。是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。

摘自CSDN:Java静态绑定与动态绑定

程序绑定的概念:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定.

静态绑定:在程序执行前方法已经被绑定(也就是说在编译过程中就已经知道这个方法到底是哪个类中的方法),此时由编译器或其它连接程序实现。例如:C。
针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定

动态绑定:后期绑定:在运行时根据具体对象的类型进行绑定。
若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说,编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。

略复杂,后面再补充。

 

第二章 类与对象(需补充点:1)


这一章着实没什么记的。

对象也可以称为实例。

记一些英语单词:

  1. 实例变量:instance variable
  2. 方法:methods
  3. 封装:encapsulation
  4. 继承:inheritance
  5. 多态:polymorphism
  6. 常量:constant

Java的垃圾回收机制

创建对象时,对象会被存放在堆中,无论对象是如何被创建的。而且这个堆并不是普通的堆,而是回收垃圾堆(Garbage-Collectible Heap)。会根据对象的大小分配空间。并且回收清理对象的动作由JVM检查到内存不足时自动执行。后面还会更详细的讲述回收垃圾堆。

在Java中的全局变量(global)

Java中没有全局变量,是用public static final实现的。

关于提交大量类文件

可以把所有文件包装进依据pkzip格式存档的Java Archive-.jar(什么是jar?)文件,并在jar文件中引入manifest(什么是manifest?)文字文件,文件中定义了jar中哪个一个类启动程序的main方法。

第三章 primitive类型和引用(需补充点:1)


(variables must have a type and name)

这一章主要记得是引用变量(reference),这个书的翻译有点乱,到底是引用对象变量还是对象引用对象。所以多学英语很重要。


2018.7.21补充

primitive主数据类型:boolean、char、byte、short、int、long、float、double(没有string)。


2018.8.10补充

非primitive的变量只保存对象的引用。


Primitive

  1. float f =23.5f(不加f则会被java认定为double处理)
  2. 变量无法存储比容量大的值(这句话怎么说更术语一些?),其实也不是不能存储,而是会发生溢位,被编译器阻止了这种动作。
  3. 但是变量可以存储比容量小的值。(这句话怎么说更术语一些?)
  4. *byte可以放进int尺寸的变量,这成为
  5. primitive主数据类型变量值是该值的字节所表示的。(这句话有点绕,要和reference一起来说,reference是以字节表示取得对象的方法。。)
  6. Java中的Boolean和其他类型不相容,if(1)这种。
  7. 布尔表达式:最好每个表达式都加上括号。长运算符的作用是boolean表达式强制jvm一定计算两边的表达式。但通常是做位的运算。(并不是该章内容,但是放在这很合适)

Reference

  1. 需要知道的是,并没有对象变量这种东西。只有引用对象变量reference。书中说的遥控器的比方很恰当。
  2. 引用对象只会保存引用。
  3. reference并不是对象的容器(它不真正存储对象),而是一个类似指向对象的指针。
  4. 对象只会存在可回收垃圾的堆上
  5. (变量值是取得特定对象的位表示法)
  6. reference会被永远固定成声明的对象类型。
  7. reference的大小我们并不知道,但是所有的对象引用都具有相同大小。不论类型(?)
  8. *final还有另外的说法,后面讲。
  9. null也是一个值,当reference被赋值了null,且reference是该对象的唯一引用,那就意味着没有其他变量能引用该对象。而该对象就只有被回收的命运。
  10. 两个reference可以引用同一个对象(虽然是废话但是还是要说)reference A更改了对象的状态,则reference B 还是会更改。(补充,确认)
  11. 只要对象还在被引用,就不会被回收。(也是废话)

Array

  1. 数组变量就是数组对象的遥控器。(数组也是对象
  2. 一旦数组被声明出来,只能装所声明类型的元素。
  3. *byte可以放进int数组中(小到大),也就是隐式展开

隐式转换就是系统默认的、不需要加以声明就可以进行的转换 [1] 。一般情况下,数据的类型的转换通常是由编译系统自动进行的,不需要人工干预,所以被称为隐式类型转换。但如果程序要求一定要将某一类型的数据转换为另外一种类型,则可以利用强制类型转换运算符进行转换,这种强制转换过程称为显式转换。

 

第四章 方法操作实例变量(需补充点:1)


这一章重点讲的是getter和setter的意义,要明白这两个东西存在的道理。同时讲了同一个类型得每个对象可以有不同的方法行为。以及实参(argument)和形参(parameter)。

Java是通过值传递的(通过拷贝传递)。例:变量x传入方法go(z),z的值改变并不影响x,传给z的只是拷贝。(传入的实参为对象另说)方法无法改变调入方所传入的参数。

方法的参数

  1. 方法运用形参,调用的一方传入实参。
  2. 对方法传入对象参数,实际上传的是远程控制的拷贝。
  3. 可以隐式转换返回成其他类型值,如byte当作int型返回。
  4. Java并没有要求一定处理返回值,如果不处理返回值,就代表着只想使用方法而不是要返回值。
  5. 方法声明了非viod的返回类型,则一定要返回和声明类型相同的值。

封装(encapsulation),getter,setter

直接通过远程控制修改对象的实例变量,这样不安全,而且容易将变量修改成异常值。在setter中可以设定一些限定条件和必要的记录操作,可以退回不合理的值,抛出异常。getter同理。

并且,封装还可以随时修改setter和getter而不影响其他的代码。

  1. int x = objecta.getterA();(可以在初始化时使用getter来初始化变量。上次书上画了重点符号,其实我不明白为什么画)。
  2. 要强制给所有实例变量设置setter和getter
  3. 将实例变量标记为private,将getter和setter标记为public。即可完成封装。

关于变量的补充:实例变量永远都会有默认值,无论是否初始化还是设置setter。但是局部变量没有默认值。所以使用前必须初始化。(*方法中的参数如何?

方法中的参数是在参数列声明的,其实它也是局部变量。但是他不会出现未初始化的编译器报错。因为当调用方法而为赋值参数时就已经提前报错了。

 

变量的比较

==只是在比较变量的字节组合。若想知道对象真的是否相等,要用equal

  • ==可以比较俩个primitive著数据类型是否相等
  • ==也可以比较两个引用变量是否引用到同一个对象。
  • equal可以判断两个对象是否意义上相等,如string(关于对象的比较,日后另有补充。)

这一章有许多内容是熟悉,但是记得不扎实,需要仔细看看。

 

第五章 编写程序(需补充点:1)


这一章主要是上机操作,以及上层设计。如何不用集成的编译环境手动编写JAVA程序看:Java环境配置与手动编辑运行文件

我并没有敲这一章的代码。等打完了再补充。

其中讲到了一些开发时用的方法,如:

极限编程:小规模多次发布,先写测试用的程序。

加强版的For循环

 

《读书笔记:HeadFirst Java (上)》

变量类型间的转换

将String转换为int:Integer.parseInt(“3”)

转换primitive主数据类型(cast):

虽然在前两章讲过:long比int大,所以把long给int是不会通过编译的。但是使用cast原算符可以强制赋值通过编译,尽管这样数据会很*诡异

重点是,可以通过编译。

 

第六章 认识Java的API(需补充点:4)


这张讲的是Java的API以及对Array list的讨论。

API是什么?

ArrayList

存在于Java函数库中的一个类。ArrayList会存放在堆上。

方法:

《读书笔记:HeadFirst Java (上)》

我在看着章时没头没脑的记下了:*int需要new吗?不知道为什么会写这句。可能是说把”int存放在ArrayList中需要new吗?”。这个类似的问题下一章有解答。

ArrayList在5.0之前无法直接保存主数据类型,只能封装。在5.0可以自动封装。

*数组是对象但是有自己的规则,并不能调用它的方法,只能存取length实力变量。

 

比较ArrayList与一般数组

  1. 一般数组在创建时需要确定大小。(没有malloc吗) ArrayList不需要。
  2. 存放对象给一般数组需要指定位置。ArrayList不需要。
  3. 一般数组使用特殊语法,如方括号。ArrayList只是普通对象,没有特殊语法。
  4. 在Java5.0中,ArrayList是参数化的(parameterized),使用ArrayList<String>来代表ArrayList中的存在集合的类型。(5.0之前是无法声明存放的元素类型,只会是异质对象的集合)。*在后几章对参数化类型会有更多讲解。

Java API

  1. 每个类都属于某个包。
  2. 除非来自java.lang包中的类,否则要在代码中指明类的完整名称,如import java.until.ArrayList或者用到就打全名。
  3. 程序不会因为import而变大或慢。
  4. java.lang是被预先引用的包。

第七章 继承与多态(需补充点:2)


继承和多态的基本概念和用途就不写了,面向对象的基本特质。

覆盖(overide)

  • 覆盖方法要履约。方法就是合约的标志
  • 实例变量无法覆盖掉是因为不需要。
  • 调用对象引用的方法时,会调用最低阶的方法。
  • 覆盖的参数必须要一样,返回类型要兼容(参数为什么不能是兼容?)
  • 不能降低存储权限,只能更开放。(若被标记为private,便一会通过,但是执行期间会出错)

继承(Inheritance)

几个需要看一眼的点

  • 说到类的成员时,成员就是实例变量方法
  • *可以用IS-A测试检验是否应该设计继承类。
  • super可以调取父类的方法。
  • 并没有私有类,但是可以有*内部类。
  • 有三种方法可以实现防止某个类被做出子类,存取控制、final、构造函数private

以及:

public类型的成员会被继承,private类型的成员不会被继承。*方法中如果使用的private变量呢?

继承可以确保子类都会有父型所持有的全部方法。

多态(polymorphism)

多态下引用与对象可以是不同的类型(引用类型可以是实际对象类型的父类)

Animal myDog=new Dog();

例如:

《读书笔记:HeadFirst Java (上)》

当然参数和返回类型也可以多态:

《读书笔记:HeadFirst Java (上)》

重载(overload)

  • 重载和多态没有关系
  • 返回类型可以不同,但是不能只改变返回类型而参数一样。
  • 可以更改权限

第八章 接口与抽象类(需补充点:2)

抽象类(abstract)

有一些类不应该被初始化,通过关键词abstract变成抽象类,编译器就不会允许初始化抽象类。

抽象类可以带有非抽象的方法,可以有成员变量

抽象类除了被继承外没有别的目的。

抽象类可以作为引用类型(为了多态)。

抽象的方法

方法也可以标记为抽象。

例:public abstract void eat();

如果声明抽象方法,类必须要标记为抽象的。

抽象方法就是为了多态存在,没有内容。

抽象的方法一定要被实现。

Object

(这一节翻译有问题,object和Object都翻译成了”对象”)

Java的所有类都是由Object继承来的(没直接继承的,会隐含继承)。

Object和引用类型可以是父类一样,返回值和参数都可以说Object

Object不是抽象的而且可以创建对象,其中有许多自己的方法(tostring),部分方法可以覆盖。

Object的目的是多态,应对多种类型。还有就是*线程

使用Object的一些问题

把所有对象变为Object会使对象失去本质。无法调用原类型的方法,也无法赋值给原类型的变量(引用变量)。

从ArrayList<Object>取出的东西会被当作Object类型,而不是原来的类型。

编译器根据引用类型判断method是否可以调用,而不是根据Object的确实类型。

多态意味着很多种形式

《读书笔记:HeadFirst Java (上)》

什么类型,用的就是什么遥控器。java很注重引用变量的类型

引用变量的类确实有该方法才能调用,而类的公有方法就是合约的内容,对其他程序使用此类的保证协议。

转换Object为原类型

《读书笔记:HeadFirst Java (上)》

《读书笔记:HeadFirst Java (上)》

接口(interface)

一个问题:给每个对象设同名方法会不会引起多态?

接口可以初始化吗?

多重继承会引起“致命方块”的问题。所以不允许多重继承。

接口是纯的抽象类。

接口的定义:

public interface xxx{}

接口的实现(可以多重继承)

public class xxx extends xxx implement xxx,xxx,xxx{}

接口的方法带有public和abstract。但都是选择性的。接口内的方法都是抽象的。

书上说;使用implement必须还在某个类继承之下?(when you implement an interface you still get to extend a class)

接口的目的

多态,可以取代具体的类作为参数或返回类型。

调用父类方法

super

接口和抽象类还有很多疑问,第十章写完回来补充。

第九章 构造器和垃圾收集器(需补充点:2)


栈(stack)和堆(heap):生存空间

《读书笔记:HeadFirst Java (上)》

对象存在堆中,*实例变量存在堆中。

局部变量和方法的参数都是被声明在方法中,是暂时的。生命周期只有放在栈中这一段时间。

引用变量本身也只会放在栈上。

方法会堆在栈中。

实例变量

*实例变量:声明在类中,方法之外的地方。

实例变量有默认值。

实例变量存在堆中,对象的空间大小必须足以存放对象中所有实例变量的空间。

实例变量若是个对象,则留下的空间是引用对象的大小,并不是对象变身的大小。

(所以说是可以在类中创建对象的。这句虽然很蠢但是要记下来,因为在早期看书的时候我确实发出了这样的疑问。)

若实例变量对象只是声明,没有赋值。则只会留下变量的空间。引用变量赋值后,其引用的对象会在堆上占有空间。

构造函数

抽象的类也有构造函数。

构造函数不是方法。要使用构造函数只能新建类。

编译器会帮忙写,并且只会在完全没有设定构造函数时才会帮忙。

构造函数是在对象赋值给引用之前执行。

不会被继承。

如果写了有参数的构造函数,编译器不会帮你写没有参数的版本。如果你需要无参数的,只能自己写。

重载构造函数参数绝对不能一样(参数顺序,类型。重载的规定)。

构造函数可以是公有,私有或者不指定。*后面会有讨论。

被标记为私有的构造函数可以限制非抽象类被初始化。

继承和构造函数

创建对象时,所有继承的构造函数都会执行。(私有的构造函数怎么办??)

继承关系的构造函数会连锁反应,不停的先执行父类的构造函数,连锁反应到Object类为止。

父类的构造函数永远是在栈中最先执行的:

《读书笔记:HeadFirst Java (上)》

调用父类构造函数

可以用super(),且super();必须放在第一句。super可以带参数。

如果没有调用,编译器会帮忙调用super(),而且帮忙调用的一定是无参数的(*要是没写无参数版本呢?);

this

this可以调用类中其他构造函数,和super一样,只能在第一句中用。

和super有冲突。

this本身其实就是对对象的引用。

对象的生存时间

局部变量只能生活在方法中,栈中一旦没了该方法,局部变量也就消失了。

引用变量的生命周期对堆中的对象有影响,一旦对象的唯一引用死了,就会变为可回收的(不是立即回收)。

null会抹掉引用变量的所有内容。

第十章 数字与静态()


Java中没有global。*BrainBarbell中的问题没看懂。

静态(static)方法

static可以标记出不需要类实例的方法(当然也可以用对象调用静态方法,但是没必要)。

静态方法不能调用非静态的变量(因为是无关特定类的实力情况下执行的,所以不可能使用到任何实例变量,同时静态方法也不会知道实例变量),也不能调用非静态的方法。

静态(static)变量

*静态变量可以是对象吗?

被同类的所有实例共享(*父类的静态变量可以使用吗?)。

在类被加载时初始化,并会在该类任何对象创建之前、任何静态方法执行之前,完成初始化。

静态变量会自动设定默认值。

final

图中的内容很重要,static静态初始化方法:

A static initializer is a block of code that runs when a class is loaded, before any other code can use the class, so it’s a great place to initialize a static final variable.(懒得打字,照抄了)

只有这一个组合可以实现一个常量(大写):

public static final double PI = 3.141592653589793;

final不只用在静态变量上,final的非静态变量代表不能改值,final的method不能被覆盖,final的类不能被继承。

非静态的方法可以使用静态方法和变量。(这句书上翻译错了,特意记下。下图是原话。)

 

《读书笔记:HeadFirst Java (上)》

final的静态变量值必须在声明或静态初始化中赋值。

主数据类型的包装

5.0版本之前的arraylist是无法add(int)的。其实每个著数据类型都有包装用的类,名字也和类型名不大一样。

并且integer这种包装类,和著数据类型也没什么关系,只不过integer中有个变量是int。引入autoboxing后就省事多了。

autoboxing

autoboxing可以主动将主数据类型包装。

没有ArrayList<int>这种写法,只能指定类或者接口。

autoboxing还可以用于方法的参数,返回值等等。也可以和int一样直接运算。

Sharpen your pencil 有问题 

包装、转换主数据类型

包装中有一些静态方法,如integer.parseInt()、to.string、字符串和数字加减(+号是java中唯一的重载运算)之类的。

数字的格式化(Formatter)和格式化说明

《读书笔记:HeadFirst Java (上)》

必填的是类型。

java.util.Calendar

Calendar是一个抽象的类,可以取得各地区的日历规定。由于是抽象类,所以不能初始化来获得实例,只能通过:

Calendar cal = Calendar.getInstance();

*Calendar的具体API以后用到再说。

import

可以导入静态类、变量、enum,总之就是少打几个字。如:

 

END


前十章就结束了,笔记越写到后面约潦草。同时也感受到了这本书的知识点有多散,和读一本英文原版书有多重要。下面的八章就另一篇文章写,文章不好分页太长了。

发表评论

电子邮件地址不会被公开。 必填项已用*标注