Java-01 《Head First Java》主要知识点总结

前提概要

  • Java的工作方式
    源代码=》编译器=》产出字节码( 生成.class文件)=》 Java虚拟机(JVM)
  • 程序要做的事情
    你会编写源代码文件(.java),用javac编译程序把文件进行编译(输出.class文件,这个文件由字节码组成),然后在某个Java虚拟机上执行编译过的字节码(JVM会将字节码转换成平台能够理解的形式来运行)

1、Java的primitive主数据类型有三种
boolean与char,数值 (带正负号)
数值分为六种: byte\short\int\long\float\double
2、如果实例变量定义了,但是没有赋值,默认值,数值类型会是0,Boolean类型是false,对象类型是null
null代表没有操作对象的远程控制,它是个引用而不是对象

3、对象和类的区别
类是对象的蓝图。它会告诉虚拟机如何创建某种类型的对象。根据某类创建出的对象都会有自己的实例变量
举例:
编写类=》编写测试用的类=》在测试用的类中创建对象并存取对象的变量和方法

4、main方法,是程序的入口
由两个作用:一个是测试真正的类,二是启动你的Java应用程序
5、实例变量和局部变量的区别

  • 实例变量是声明在类中,而不是方法中
  • 局部变量声明在方法中,且没有默认值,如果在变量初始前使用,编译器会显示错误
  • 局部变量在使用前,必须初始化
  • 方法的参数也是局部变量,但是方法调用时,肯定会初始化,所有编译器不报错

6、变量的比较有“==”和equals()两个方法

  • 两等用于比对两个变量的字节组合,用于判断primitive主数据和两个引用变量是否引用到同一个对象

7、for循环有两种

  • 基础版:for (int i =0 ; i < 8 ; i++) {}
  • 加强版: for(String name:nameArray){}

8、primitive主数据可以进行转换,通过cast运算符

long y=42;
int x=(int)y;
short z = (short)y;

9、数组和ArrayList的区别

  • 在使用ArrayList时,你只是在运用ArrayLi st类型的对象,因此就跟运用其他的对象样你会使用. 运符来调用它的方法
  • 使用数组时,你会以特殊的数组语法来操作. 这样的语法只能用在数组上. 虽然说数组也是对象,但是它有自己的规则,你无法调用它的方法,最多只能存取它的length实例变量.
  • 一般数组在创建时就必须确定大小,而且不能改变;

10、超强布尔表达式

  • 短运算符( && ,||),遵循短路原理
  • 不等于运算符(!=和!)
  • 长运算符( &,|):该运算符使用在Boolean表达式时会强制Java虚拟机一定要计算运算符两边的算式. 但这两个运算符通常是用来作位的运算.

11、使用函数库

  • System (Syslem.out.println),String与Math ( Math.random)属于java.lang这个包.
  • 你必须指明程序代码中所使用到的类的完整名称,除了java.lang
  • javax代表标准版的扩展
  • import只是帮你节省每个类前面的包名称而已,不会因为用了import而变大或者变慢
// java.util包名,ArrayList类名
java.util .ArrayList 
- 放一个Import述句在程序源文件的最前面
```
    import java.util .ArrayList
```
 - 第二种方式,在每个使用的地方打出全名
  ```
  java.util .ArrayList<Dog>  List  = new   java.util .ArrayList<Dog>()
  ```

12、查询API,了解Java有哪些类
Java17中文文档 - API参考文档 - 全栈行动派

13、在 Java 中,IS-A 测试(也称为类型检查)是一种判断对象是否属于某个特定类型(类、接口)的机制。它用于在运行时验证对象的继承关系或接口实现,确保代码安全地处理不同类型的对象。
14、存取权限(access level ) 控制了谁可以接触什么
下而列出这4种权限,左边是最受限制的,而越往右,限制越小
private default protected public

  • private类型成员不会被继承
  • public类型成员会被继承

15、《Head First 设计模式》
16、继承

  • 子类继承父类使用extends
  • 如果既继承父类,又覆盖一部分,使用super调用方法
    17、多态
  • 在多态下,引用类型和对象可以是不同类型,比如引用是Animal,对象是Dog
Animal dog = new Dog()
  • 任何extends过声明引用类型的对象,都可以赋值给这个引用变量
Animal[] animals= new Animal[4]
animals[0] = new Dog()
animals[1] = new Cat()
animals[2] = new Wolf()
animals[3] = new Hippo()
  • 参数和返回类型也可以是多态
  • final修饰符:如果用它标识类,表示被修饰的类是继承树的末端,不能被继承;如果标识方法,表示该方法不可以被覆盖

18、覆盖的原则

  • 参数必须要一样,且返回类型必须兼容:子类对象得保证能够执行父类的一切
  • 不能降低方法的存取权限

19、方法的重载:两个方法的名称相同,但参数不同
注意:重载版的方法只是刚好有相同名字的不同方法,它与多态或继承无关,重载的方法与覆盖的方法不同

  • 返回类型可以不同
  • 不能只改变返回类型
  • 可以更改存取权限

20、抽象类: 可以继承和产生多态, 但是要限制只有它的子类能够被初始化

  • 关键字:abstract class
  • 抽象类除了被继承过之外,是没有用途,没有值,没有目的的

21、不是抽象的类,就被称为具体类
22、抽象的方法:此方法一定要被覆盖过

  • 关键字: abstract
  • 抽象方法没有实体
public abstract void eat();// 没有方法体,直接以分号结尾
  • 抽象方法只能在抽象类中定义,如果一个类里面有方法被定义为抽象方法,这个class必须也定义为抽象类
  • 好处是实现多态,每一个子类里面,都有这个方法
  • 在继承树结构下的第一个具体类必须要实现出所有的抽象方法

23、在Java中的所有类都是从Object这个类继承出来的

  • 对象会带有从父类继承下来的所有东西,这代表每个对象,不论实际类型,也会是个Object的实例
  • 把Object类型转换成Dog类型
ArrayList<Object>  myArrayList = new ArrayList<Object>()
Dog aDog = new Dog()
myArrayList.add(aDog)
Object o = myArrayList.get(0) // o会被当成Object的实例,失去dog的相关属性
// 如果想恢复成dog,可以采用以下方式
Dog d = (Dog)o 
// 如果不确定类型,可以加类型判断
if(o instanceof Dog){
  Dog d = (Dog)o
}

24、致命方块:一个类继承多个类(多重继承)时,如果存在同名的方法或者变量,无法选定哪个有效

  • 解决方法,使用接口Interface,把全部的方法设置为抽象
  • Java的接口就好像是100%的纯抽象类

25、接口的定义和实现

// 接口定义
public  interface Pet{}
// 接口实现
public class Dog extends Canie implements Pet{
  public abstract void beFriendly();// 接口方法一定是抽象类,所以必须分号结尾,没有内容
  public abstract void play();
}
// 类可以实现多个接口
 public class Dog extends Canie implements Pet,saveable{}

26、实例变量是被声明在类而不是方法里面,实例变量存在于所属的对象中

  • 实例变量存在于对象所属的堆空间上

27、局部变量和方法的参数被声明在方法中,他们的生命是暂时的,仅存在于方法执行阶段,也就是方法调用到执行完毕为止

  • 所有的局部变量都存在于栈上相对应的堆栈块中

28、唯一能够调用构造函数的方法就是新建一个类

  • 构造函数带有你在初始化对象时会执行的程序代码,也就是新建一个对象时就会被执行
  • 构造函数没有返回类型,函数名与类名相同
public Duck(){
  // 构造函数代码在此
}
  • 构造函数可以让你介入new的过程
// 如下,构造函数代码会在每一个Duck实例中执行
public class Duck(){
    public Duck(){
        // 构造函数代码在此
    }
}
  • 大部分人使用构造函数初始化对象的状态
  • 一个类可以有两个构造函数,一个有参数,一个没有参数
  • 编译器只会在没有构造函数的时候,创建一个没有参数的构造函数;如果已经有一个有参数的构造函数,必须自己手动写一个没有参数的
  • 如果类有一个以上的构造函数,则参数一定要不一样
  • 在创建新对象时,所有继承下来的构造函数都会执行

29、构造函数链

  • 创建子类对象,也会同步构建父类对象,这就形成了构造函数链,而且父类对象的构造函数先执行
  • 调用父类构造函数的唯一方法是调用super()
  • 如果我们没有调用super(),编译器会帮我们加上
  • 如果父类有多个重载的构造函数版本,只会调用没有参数的版本
  • 父类的部分必须在子类创建之前就完整的成型(就像必须现有父母后有子女一样),所以supper()的调用必须是构造函数的第一个语句
  • 子类型先被调用,但是是最后一个完成

30、从某个构造函数调用重载版的另一个构造函数

  • 使用this()来从某个构造函数调用重载版的另一个构造函数
  • this()只能用在构造函数中,且必须是第一行语句
  • super()和this()不能兼得

31、 对象的生命周期:完全看引用它的“引用”

  • 局部变量只会存活在声明该变量的方法中
  • 实例变量的寿命与对象相同

32、life和scope的区别

  • life: 只要变量的堆栈块,还存在于堆栈上,局部变量就算活着,如果声明它的方法在执行 中,它就能被调用,但是如果声明它的方法不在执行中,它虽然活着,但是它不在当前执行方法的scope内,所以不能被调用
  • scope: 局部变量的范围只限于声明它的方法之内。当此方法调用别的方法时,该变量还活着,但是不在目前的范围内,执行其他方法完毕返回时,范围也就跟着回来了。

33、静态方法 static:不需要类实例的方法,比如Math

  • 一种不需要实例变量也就不需要对象的行为
  • 以类的名字调用静态方法,比如Math.min(88,68),以引用变量的名称调用非静态方法:Song t2 = new Song() t2.play()
  • 静态方法不能调用非静态的变量,也不能调用非静态的方法

34、静态变量:它的值对所有的实例来说都相同

  • 静态变量:每个类一个;实例变量:每个实例一个
  • 如果没有给静态变量赋值,它就会被设置默认值,int-->0,浮点数 --> 0.0,boolean-->false,对象引用-->null
  • 静态的final变量是常数,常数变量的名称应该要都是大写
public static final double PI = 3.141592653589793
  • 如果类只有静态的反复,可以奖构造函数标记为private,以避免被初始化
    35、final
  • final的变量代表你不能改变它的值
  • final的method代表你不能覆盖掉该method
  • final的类代表你不能继承该类(也就是创建它的子类)

36、封装类型和数据类型转换

  • int => string,可以使用'' + number
  • 格式话使用formate()方法,%代表传入的参数
format( "%,d" , 1000000000);  // 1,000,000,000
format("I have %.2f bugs to fix", 45.09876)  // I have 45.10 bugs to fix
format("I have %,.2f bugs to fix", 45678.09876)  // I have 45,678.10 bugs to fix
  • 要取得当前日期时间用Date,其余功能可以从Calendar上面找

37、import static 导入类中的静态成员(如静态方法或静态变量),不能用于导入类本身
38、异常处理

  • 使用try..catch..finally
  • 异常是一种Exception 类型的对象
  • 在类的后边定义throws + 错误类型
  • 实际抛出异常的情况有两种
    - 方法体内显示throw异常
    - 方法体内调用了其他可能抛出异常的方法,并且没有用try-catch捕获,而是直接向上抛出,这叫duck异常
       // 并没有try/catch块来处理有风险的方法,因此这个方法本身就是又风险的
       public void foo() throws ReallyBadException{
         // 调用有风险的方法
       laundry.doLaundry()
      }
  - 异常支持多态,可以定义多个异常

39、 序列化(保存对象

  • 核心含义:
    是将 Java 对象(包括其状态信息,即成员变量的值)转换为字节序列的过程。这样做的目的是方便对象的存储(如写入文件)或网络传输。与之对应的是反序列化,即把字节序列恢复为原来的 Java 对象。
    简单说,序列化就是把 "活生生" 的对象 "冻结" 成字节流,反序列化则是把字节流 "解冻" 回对象,让它能在另一个地方(如另一台电脑、另一个进程)继续使用
  • 序列化的主要目的是对象的持久化存储或跨平台 / 跨进程传输,它会保留对象的完整结构和数据,生成的字节流通常包含额外的类元信息(如类名、属性类型等),体积可能比原始数据更大
  • 数据压缩的目的是减小数据体积,通过算法(如 ZIP、GZIP)去除冗余信息,不涉及对象结构的转换,压缩后的数据只是原始数据的紧凑形式,不能直接恢复为对象
  • 序列化程序会将对象版图上的所有东西存储起来,被对象实例变量所引用的所有对象都会被序列化
  • FileOutputStream:把字节写入文件
  • ObjectOutputStream: 对象被碾平,把对象转换成可以写入串流的数据
  • 如果要让类能够被序列化,就实现Serializable,唯一目的是声明有实现它的类是可以被序列化的
import java.io.* // 必须import
// Serializable 没有方法需要被实现,只是用来告诉Java虚拟机,它可以被序列化
public class Box implements Serializable {
  
}
  • 序列化时全有或者全无的,不存在部分成功的场景
  • 如果某些实例变量不能或者不应该被序列化,就把它标记为transient

40、解序列化(还原对象)

  • FileInputStream
  • ObjectInputStream

41、通过序列化聚在储对象是lava程序在来回执行闹符储和恢复数馆最简
单的方法
42、将字符串写入文本文件

import java.io.*
class WriteFile {
  public static void main (String[] args){
    try {
      FileWriter writer =  new FileWriter("Foo.txt")
      wirter.write('Hello World')
      writer.close()
     } catch (IOException ex ) {
        ex.printStackTrace()
    }
  }
}

42、java.io.file class

  • File 这个类,代表磁盘上的文件,不代表文件内容
  • 可以创建删除文件,返回文件的路径
  • 写入文件时,为了提高磁盘写入效率,可以使用缓冲区
  • 读取文件也用这个类

43、序列化时,写入和读取时的类要保持一致

  • 通过serialVersionUID实现
  • 通过serialver工具来取得版本

44、jar包的部署

  • 三种方式:本机,半本机半远程,远程
  • 将源代码和类文件分开:编译的时候加修饰符号 -d
  • JAR:Java ARchive--这种文件是个pkzip格式的文件,它能让你把一组类文件包装起来
    45、创建可执行的JAR步骤如下
  • 确定所有类文件都在classes下
  • 创建manifest.txt文件,描述哪个类带main()方法,此文件放在classes文件夹下
Main-Class: MyApp
  • 执行JAR工具创建JAR
jar -cvmf manifest.txt app1.jar *.class

46、把类包进包里

  • 最好包名和目录结构相对应
package com.headfirstjava
public class packageExercise{}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容