Head First Java读书笔记
2023-03-24 08:48:57 0 举报
AI智能生成
Head First Java 读书笔记
作者其他创作
大纲/内容
1、基本概念
优点
友好的语法、面向对象、内存管理、跨平台可移植性
工作方式
javac编译.java文件,生成.class文件(字节码)
启动Java虚拟机运行.class文件
Java版本
Java:Java1.02~Java1.1
Java2:Java1.2~Java1.4
Java5:Java1.5
重要知识点
Java中integer和boolean两种类型不相容
每个Java程序至少一个类和一个main
2、类和对象
在堆中创建对象,可回收垃圾的堆。
变量加上public、static和final,变成全量变量
任何java中的事物都必须待在类中,pi常数和random()方法也必须定义在Math这个类中
把文件依据pkzip格式打包为.jar文件,通过manifest定义jar中哪一个文件带有启动应用程序的main方法
3、primitive主数据类型和引用
浮点数
float
32bits
double
64bits
一个小数,除非加上f,否则所有带小数的值都会被java当成double处理
boolean
char
16bits
数值
byte
8bits
-128~127
short
16bits
-32768~32767
int
32bits
long
64bits
变量命名
名称必须以字母、下划线或者doller符号开头,不能用数字开头
对于primitive主数据类型的变量来说,变量值就是所代表的值,对于应用变量来说,变量值是取得特定对象的位标识法
对象的声明、创建和赋值
声明一个引用变量
在堆上创建对象
连接对象和引用
数组犹如杯架,一个个变量就是杯子,杯子放到杯架上,杯子里面可能直接装主数据,也可能装载的是对象的引用。数组自身也是一个对象,空间在堆中。
4、方法操作实例变量
Java通过值传递,也就是拷贝传递
变量默认值
实例变量会有默认值,如果未初始化就会是默认值
局部变量没有默认值,如果在变量初始化前就使用的话,编译器会报错
变量的比较
==
比对两个变量的字节组合
int a = 3;
byte b = 3;
if (a == b)//true
byte b = 3;
if (a == b)//true
判断两个引用是否引用同一个对象
5、编写程序
极限编程(XP)
多次小规模发布
避免加入规格没有的功能
先写测试 用的程序
随时随地重构
保持简单
结对编程,并经常交换结对
6、认识Java的API
要使用API的类,需要知道放在哪个包中
import可以省下每个类前面的包名称
java.lang是个预先被引入的包,可以不必须制定名称,java.lang.String和java.lang.System是对一无二的class,Java知道要去哪儿找
7、继承和多态
子类会继承父类所有public类型的实例变量和方法,但不会继承父类所有private类型的变量和方法
继承下来的方法可以被覆盖掉,但实例变量不能被覆盖掉
多态
运用多态时,引用类型是实际对象类型的父类,参数和返回值也可以多态
通过动态,引入新的子类型也不必修改程序
如何阻止某个类被继承
存取控制,不标识为公有,非公有的类只能被同一个包的类作出子类
使用final修饰符
让类只拥有private的构造程序
如果只是想要防止特定方法被覆盖,可以将该方法标识上final修饰符
覆盖的规则
参数必须要一样,返回类型兼容
不能降低方法的存取权限
重载(overload)
方法名称相同,但参数不同,重载和多态毫无关系
返回类型可以不同,不能只改变返回类型
可以更改存取权限
8、接口和抽象类,深入多态
抽象类
有些类不应该被初始化
设计为抽象类,在类声明前加上关键词sbstract
抽象方法
此方法一定要被覆盖
如果声明出一个抽象方法,必须将类标记为抽象类,不能在一个非抽象类中拥有抽象方法
抽象方法的意义在于无法实现方法的内容,但还是可以定义出一组子型共同的协议
抽象的方法没有内容,它只是为了标记出多态而存在
对象之母Object
在Java中所有的类都是从Object这个类继承出来的
Object不是抽象类,它没有必须要被覆盖掉的方法
可以部分覆盖Object的方法,比如hashCode、equals、toString
Object通用对象、轻量化的对象,最常见的用途是用在线程的同步化
Java是类型检查很强的语言,如果某个对象用Object类型来引用,Java会把它当成Object类型的实例,只能调用Object类中声明的方法
任何从ArrayList<Object>取出的东西都会被当成Object类型的引用,而不管它原来是什么,需要将Object类型转换为原来类型,才能调用原有类型的方法
接口
使用接口可以解决多重继承的问题,Java不运行多重继承,因为那样会有致命方块的问题
Java的接口就好像是100%的纯抽象类
接口的方法一定是抽象的
如果想要定义出类可以扮演的角色,使用接口
调用父类的方法
super.XXX()
子主题
9、构造器和垃圾收集器
栈与堆
方法调用和局部变量在栈上
非primitive的变量,保存的是对象的引用,如果是具备变量,变量在栈上,对象在堆上。
实例变量存在于对象所属的堆空间上
构造函数
如果没有构造函数,编译器会写一个
构造函数没有返回值,方法名和类名称相同。如果有返回值,那么就是方法,不是构造函数。
如果写了一个有参数的构造函数,并且需要一个没有参数的构造函数,那么必须自己动手写。编译器只有在完全没有构造函数的时候,才会自动生成一个构造函数。
构造函数可以以公有、私有或者不指定
在创建新的对象时,继承下来的构造函数都会执行,构造函数链
编译器会自动加上父类构造函数的调用supper(),编译器自动加的一定是没有参数的版本,假设父类有多个重载版本,也只有无参数的版本会被调用
有参数的父类构造函数需要显式调用
使用this可以调用同一个类的另外一个构造函数,this只能在构造函数的第一行,supper和this不能兼得
null
不能对null引用使用圆点运算符,会抛异常
10、数字与静态
静态方法
static关键字,不需要类实例的方法
静态方法不能调用非静态的变量
静态方法不能调用非静态的方法
可用使用引用变量替代类名称来调用静态方法,但是不推荐这样做
静态变量会在该类的任何对象创建之前或者该类的任何静态方法执行之前就会初始化
final
静态的final变量是常数,在类加载之后静态final变量就一直会维持原值
初始化
在声明的时候直接初始化
在静态初始化程序中
static {
XXX
}
XXX
}
final的method代表不能覆盖掉此method
final的类代表不能继承该类
如果一个类只有静态方法,可以将构造函数标记为private以避免被初始化
primitive主数据类的包装
在Java5.0之前,当需要用对象的方式处理primitive主数据类型时候,需要包装
包装类
Boolen
Character
Byte
Short
Integer
Long
Float
Double
解开包装
调用类方法解开包装 int unWarpper = iWarp.intValue()
不能直接声明ArrayList<int>
generic类型的规则是只能指定类或者接口类型,ArrayList<int>将无法通过编译
子主题
类型转换
String转换为primitive主数据
Integer.parseInt(s)
Double.parseDouble(s)
primitive主数据转换为String
使用 + 操作符,Java中唯一有重载过的操作符
"" + d
Double.toString(d)
数字的格式化
String.format("%,d", 100000000)
%,d
十进制整数,带逗号
%.2f
小数点保留2位来格式化此浮点数
%,.2f
整数部分以逗号形势标识,小数保留2位
日期格式化
%tc
完整的日期和时间
%tr
只有时间
%<tB %<td
<用来告诉格式化程序重复利用之前的参数
要取得当前的日期时间用Date,其他功能可以从Calendar上面找
Calendar.getInstance()
静态import
import static java.lang.System.out
out.println()
out.println()
使用的时候可以少打个字,但是会带来名称冲突
11、异常处理
如果有抛出异常,一定要用throw来声明这件事情
如果调用抛出异常的方法,需要用try/catch来处理异常
异常是Exception类型的对象
try/catch/finally
如果try或者catch块有return指令,finally还是会执行,流程会跳到finally然后再回到return指令
方法可以抛出多个异常
catch时,Java虚拟机只会从头往下找到第一个符合范围的异常处理块
catch时,异常需要从小排到大
异常多态
可以不必明确声明每个可能抛出的异常,只声明父类就可以
catch块可以不对每个异常做处理,只要一个或者少数几个catch就可以处理所有的异常
不想处理异常时,duck掉异常
有申明会抛出异常,但是没有try/catch块,会duck掉异常留给调用方
12、图形用户接口
13、swing
三大管理器
BorderLayout
分割5个区域,每个区域1个组件
南北先占位高度,东西占位宽度,中间组件扣除周围剩下的
FlowLayout
流式布局,从左至右排列,有必要时换行
BoxLayout
从上到下,每行1个
就算水平宽度足以容纳组件,它还是会用新的行来排列组件
14、序列化和文件的输入输出
序列化对象写入文件
创建FileOutputStream
创建ObjectOutputStream
写入对象
关闭ObjectOutputStream
object -》ObjectOutputStream(对象被碾平)-》(连接到)FileOutputStream->文件
序列化对象
当对象被序列化时,被该对象引用的实例变量也会被序列化
如果要让类能够被序列化,就实现Serializable
implements Serializable
如果某个类是可序列化的,它的子类也自动地可以基序列化
如果某个实例变量不需要序列化,标识成transient(瞬时)变量
静态变量不会被序列化,因为静态变量每个类只有1个
解序列化(Deserialization),还原对象
创建FileInputStream
创建ObjiectInputStream
读取对象
转换为对象类型
关闭ObjectInputStream
如果对象在继承树上有个不可序列化的祖先类,那么就会执行类以及父类的构造函数
将字符串写入文本文件
使用FileWriter替代FileOutputStream
缓冲区
BufferedWriter writer = new BufferedWriter(new FileWriter(aFile));
读取文本文件
File myfile = new File("MyText.txt")
FileReader fileReader = new FileReader(myFile)
String的split()可以把字符串拆开
Version ID,序列化的识别
查看某个类的ID:serialver Dog
把ID拷贝到类上
static final long serialVersionUID = XXXXXXX
15、网络与线程
建立socket连接
java.net.Socket
需要知道服务器的IP地址和端口号
Socket chatSocket = new Socket("196.164.1.103", 5000)
TCP端口
16位宽,一个地址有65536个端口可以用,端口号范围0~65535
从0~1023的TCP端口保留给已知的特定服务使用
从1024~65535可是个人应用使用
不同的应用程序不能绑定同一个端口
使用BufferedReader从Socket上读取数据
Client <- BufferedReader(缓冲区字符) <- InputStreamReader(转换为字符) <- Socket输入流(来自服务器的字节) <- Server
使用PrintWriter写数据到Socket上
Client -> PrintWriter -> Socket输出(写上服务器的字节) -> Server
服务器程序
服务器对特地端口创建ServerSocket
客户端对服务器应用建立Socket连接
服务器创建出与客户端通信的新Socket
Socket sock = serverSock.accejpt()
返回一个新的端口和客户端通信,ServerSocket空出来等待其它客户端的连接
线程
启动新的线程
建立Runnable对象
建立Thread对象,并赋值Runnable(任务)
启动Thread
执行runnable对象的run方法
实现Runnable接口
public class MyRunnable implements Runable{}
线程调度
调度器在不同的Java虚拟机上有不同的做法,同一个程序在同一个机器上运行也会有不同的遭遇
线程的同步
使用synchronized关键字修饰方法,方法每次只能被单一的线程存取
每个Java对象都有一个锁,每个锁只有一把钥匙
锁不是在方法上,而是在对象上
同步化可能会导致死锁现象,原则上最好只做最小量的同步化,可以使用synchronized来修饰一行或数行的指令,而不必整个方法都同步化
只有有2个线程和2个对象,就可以引起死锁
静态对象也可以被同步化
假设Dog类有3个实例,那么有4个锁,3个实例的锁,还有一个类的锁,通过类的锁可以对静态对象同步化
16、集合与泛型
ArrayList不是唯一的集合
TreeSet
有序状态保持并防止重复
集合中对象必须实现Comparable类型
取用Com怕让投入参数的构造函数来创建TreeSet
HashMap
可用成对的name/value来保存和取出
LinkedList
针对经常插入或删除中间元素所设计的高效率集合
HashSet
防止重复的集合,可快速找寻相符的元素
LinkedHashMap
类似HashMap,但可记住元素的插入的顺序,也可以设定成依照元素上次存取的先后来排序
可以使用TreeSet或者Collections.sort来进行排序
泛型
泛型意味着更好的类型安全性,让问题在编译期就能发现,而不需要等到执行期才冒出来
ArrayList<Fish>
仅Fish对象的引用能加入到ArrayList中,也能确保取出来的是Fish引用
运用泛型的方法
public <T extends Animal> void takeThing(ArrayList<T> list)
T可以是Animal或者animal的任何子类
等同如下语法:public void takeThing(ArrayList<? extends Animal> lsit)
public void takeThing(ArrayList<Animal> list)
只能是Animal
如上两种都合法,但是意义不同
两种方法
Song实现Comparable,Song实现compareTo方法
class Song implements Comparable<Song>
public int comparaTo(Song s)
自定义比较器Comparator,在调用sort的时候传入比较器
class ArtisCompare implements Comparator<Song>{}
数组的类型在运行期间检查,但集合的类型检查只会发生在编译期间
万用字符?
可以操作元素,但是不能加入元素到集合中
Collection API
Collection(interface)
Set(interface)
TreeSet
LinkedHashSet
HashSet
List(interface)
ArrayList
LinkedList
Vector
Map(interface)
SortedMap(interface)
TreeMap
HashMap
LinkedHashMap
Hashtable
对象相等
hashCode相等
大部分Java版本依据内存位置计算此序号
equals方法返回true
17、发布程序(包、jar存档文件和部署)
部署的三种场景
本地部署
用户本地客户端,远程服务端
整个程序都在服务器端运行,客户端非Java,比如浏览器
源代码和类文件分离
编译时加上-d选项
把程序包进Jar
确定所有的类文件都在classes目录下
创建manifest.txt来描述哪个类带有main()方法
执行jar工具来创建带有所有类以及manifest的JAR文件
执行Jar
java -jar app1.jar
把类包进包中
用包防止类名称冲突
用domain防止包命名冲突
反向使用domain的名称
com.headfirstjava(反向domain).project(包).Chart(类)
package
每个原始文件只有一个包指令
第一条语句,早于import语句
编译和执行包
加上-d选项来编译
javac -d ../classes com/headfirstjava/*.java
-d选项会自动创建目录
用包创建Jar
确定所有的类文件都放在class目录下正确的相对应的包结构中
创建manifest.txt描述哪个类带有main,以及确认有使用完整的类名称
执行jar工具来创建带有目录结构与manifest的JAR文件
jar -cvmf manifest.txt packEx.jar com
只需要制定com目录就行
列出Jar内容
jar -tf packEx.jar
解开Jar包
jar -xf packEx.jar
Java Web Start
如同浏览器plugin-in的小Java程序,管理下载、更新和启动JWS程序
工作方式
客户端点击某个网页上JWS应用程序的链接(.jnlp文件)
web服务器收到请求发出.jnlp文件给客户端浏览器
浏览器启动Java Web Start,JWS的helper app读取.jnlp文件,然后向服务器请求MyApp.jar
Web服务器发送.jar文件
JWS取得JAR并调用指定的main()来启动应用程序,用户可以在离线的情况下通过JWS来启动应用程序
18、分布式计算(远程部署的RMI)
远程程序调用Remote Method Invocation
JAVA RMI提供客户端和服务端的辅助设施对象
协议
JRMP
RMI原生协议,为了Java对Java的远程调用而设计
IIOP
为了CORBA而产生(Common Object Requst Broker Architecture)
CORBA通常比RMI麻烦,若两端不全都是Java的话,就会发生一堆可拍的转译和交谈操作
客户端的辅助设施称为stub(桩)
服务器端的辅助设施称为skeleton(骨架)
创建远程服务
创建Remote接口(MyRemote.java)
继承java.rmi.remote
public interface MyRemote extends Remote{}
生命所有的方法都会抛出RemoteException
public String sayHello() throws RemoteException;
实现Remote接口(MyRemoteImpl.java)
实现Remote接口
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{}
继承UnicastRemoteObject
编写无参数构造函数,并且抛出RemoteExpetion异常
public MyRemoteImpl() throws RemoteException{}
向RMI Registry注册服务
使用rmic产生stub和skeleton
对实现类执行rmic
rmic MyRemoteImpl
产生两个helper对象
MyRemoteImpl_Stub.class
MyRemoteImpl_Skel.class
启动RMI Registry
rmiregistry
启动远程服务
java MyRemoteImpl
客户端如何取得stub对象(MyRemoteClient)
客户端查询RMIRegistry
Naming.lookup("rmi://127.0.0.1/Remote Hello")
RMI Registry返回stub对象
客户端和服务端的类文件
Client
MyRemote.class
MyRemoteImpl_stub.class
MyRemoteClient.class
Server
MyRemote.class
MyRemoteImpl.class
MyRemoteImpl_stub.class
MyRemoteImpl_Skel.class
servlet
放在HTTP WEB服务器上运行的Java程序
EJB
J2EE服务器包含了WEB服务器和EJB服务器(Enterprise JavaBeans)
EJB服务器具有一组RMI以外的服务,比如交易管理、安全性、并发性、数据库和网络功能
EJB服务器作用于RMI调用和服务层之间
Jini
使用RMI,多了2个关键功能
自适应探索(adaptive discovery)
查询服务使用IP组播技术为自己做宣传
服务向启动的查询服务注册
自恢复网络(self-healing newworks)
服务注册时,返回租约,租约需要定期更新,否则服务就会被查询服务剔除
0 条评论
下一页