《Java核心技术I》笔记
日期 说明
2021/01/31 读完了第一遍,边读边记,看的比较随意,除了第一第二章外,有些难的或者偏也都直接跳过了😜,看第二遍的时候再补回来吧 maybe。

概述

  • 第 1 章 + 第 2 章 : 这两章介绍了一些东西,比如Java的发展历史啊,Java的特性啊,以及Java的运行环境等等。特别要说的是,Java是一门面向对象程序设计语言,程序设计语言的成功取决于是否可以实现需要的功能,而不是语法的精巧性。以及JDK(Java Development Kit:Java开发工具包)与JRE(Java Runtime Environment:Java运行时环境)
  • 第 3 章 Java的基本程序设计结构:这一章讲了Java的一些基础知识,比如注释啊,8 种基本类型啊(int,short,long,byte,double,float,boolean,char),变量(如何声明,初始化变量)与常量,运算符(其中还提到了短路的概念),介绍了字符串,输入输出等(这一节其实还讲了Math的一些静态方法,不过我觉得不是很重要,需要的时候可以查嘛,所以这里就不记录了)
  • 第 4 章 对象与类:这一章介绍了面向对象思想,还有类与对象的关系,说了面向对象的一些特性,以及自定义类的一些内容,还有使用构造器时代码的执行顺序

第 3 章 Java的基本程序设计结构

1.第一个程序

public class Hello {
	public static void main(String[] args) {
		System.out.println("Hello World");
	}
}

说明

  • public(访问修饰符) 用于控制对所修饰的类或对象或字段的访问级别
  • class表示这是一个类,Hello则是这个类的类名
  • main方法是所有程序的入口
  • 大括号表示方法体的开始与结束

2.注释

//单行注释

/*
多行注释,(不能嵌套使用)
*/

/**
 * 文档注释
 * 可用于自动的生成文档
 */

3.数据类型

基本类型 位数 字节 默认值
int 32 4 0
short 16 2 0
long 64 8 0L
byte 8 1 0
char 16 2 ‘u0000’
float 32 4 0f
double 64 8 0d
boolean 1 false

4.变量与常量

变量

声明变量
int a;
String name;

即 以变量类型 变量名这种形式来声明一个变量

变量初始化

声明一个变量后,必须用赋值语句对变量进行显式初始化,如下

int a = 0;
String name = "任我行";

常量

常量就是值不会变的变量

可用final关键字来修饰常量,而且通常此常量名为大写

public final String BAIDU_URL = "www.baidu.com";

枚举类型

作用:限制变量的取值范围

如下:

    enum Size {SMALL,MEDIUM,LARGE,EXTRA_LARGE};

那么Size类型的变量只能取里边的值

5.运算符

算术运算符

算术运算符 表示
+
-
*
/
% 取模

类型转换

  • 如参与运算的两个数类型不一致,则结果为较大类型的整型
  • 强制转换:(有可能损失信息)

其他运算符

  • 二元运算符:例如x+=4;,运算符放于等号左边
  • 自增自减运算符
    • ++x 前缀形式会先加1再使用
    • x++ 后缀形式会先使用原来的值,之后才加1
  • 关系运算符:如==,!=>=之类的,还有&&||
  • 三元运算符:x>0 ? true : false如表达式为真,则为true,如假则为false

短路(&&||运算符的逻辑)

如果第一个操作数已经能够确定表达式的值,第二个操作数就不必再计算了

6.字符串

这一节其实感觉没有什么好记的。。。

String hello = "Hello";
// 取子串
String s = hello.substring(0,3);// Hel
// 判断是否相等
if(hello.equals("Hello")){
    //....
}
// 构建字符串
StringBuilder builder = new StringBuilder();
builder.append("builder");
builder.append("str");
String builderString = builder.toString();
System.out.println(builderString);

7.输入与输出

输入

Scanner input=new Scanner(System.in);
System.out.printf("请输入一个数字: ");
int num=input.nextInt();//输入
System.out.println("你输入的数字是:"+num);//输出

输出

System.out.print("普通输出");
System.out.println("输出后换行");
System.out.printf("格式化输出 %.2f", 10000.0 / 3.0);

8.控制流程

条件分支流程

普通分支语句

int a = 1;
int b = 2;
if (a > b) {
    System.out.println("a大于b");//如果a大于b则执行这个语句
} else if (a == b) {
    System.out.println("a等于b");//如果a等于b则执行这个语句
} else {
    System.out.println("a小于b");//否则就a小于b,当以上两种情况都不是的时候执行
}

条件多分支语句

int g=2;
switch(g) {
    case 1:{
        System.out.println("是1");//当g是1时执行
        break;
    }
    case 2:{
        System.out.println("是2");//当g是2时执行
        break;
    }
    default:{
        System.out.println("都不是");//当以上情况都不是的时候执行
        break;
    }
}
循环流程

根据条件,反复执行某些操作

for
	for(int i=0;i<5;i++) {//int i=0是初始值,i<5是循环条件。i++是循环后更新i的值,然后进入下一轮循环
		System.out.println("循环第"+i+"次");
	}
while
		int u=5;
		while(u>0) {//当为true时执行
			System.out.println("u="+u);
			--u;
		}
do..while
		int p=0;
		do {//无条件进入循环
			++p;
			System.out.println("p="+p);
		}while(p<5);//首先执行一次循环体后进行判断,若为true则继续进行下去
for each(增强型for循环)
for ( 类型 变量名: 数组或集合 ) {
循环体
}

与普通for循环的区别:for each循环语句的循环变量将会遍历数组中的每个元素,而不是下标值

中断控制流程的语句

break:跳出一个switch case 或者一个循环

带标签的break

int a = 1;
read_data: // 标签名(放在希望跳出的最外层的循环之前),后面跟着冒号
while (true) {
    if (a == 1) break read_data;// break后要带着标签
    System.out.println("in");
}
// 当里边发生了break read_data就会跳到下面这个语句
System.out.println("out");

主要用在一些嵌套很深的循环语句中,希望发生失误后完全跳出循环体

continue:将控制转移到最内层循环的首部

9.大数

  • BigInteger实现任意精度的整数运算
  • BigDecimal实现任意精度的浮点数运算

10.数组

  • 存储一组具有相同数据类型的数据元素的有序集合
  • new操作符创建数组,整数类型的所有元素初始化为0,boolean类型的初始化为false,对象类型的则初始化为null
  • 数组一旦被创建,长度就不能修改了
// 声明
int num[];
int[] sum;
// 静态初始化
int num[]={1,2,3,4,5}
//动态初始化
int num[]=new int[5];//预先分配内存空间
for(int i=0;i<5;i++){
	num[i]=i*3;
}

第 4 章 对象与类

1.面向对象

  • 面向对象编程,是一种通过对象的方式,把现实世界映射到计算机模型的一种编程方法。
  • 面向对象程序设计:程序由对象来组成
  • 类:构造对象的模板或蓝图
  • 对象:类的实例化

类和对象的关系好比 模具 和 具体的用模具实际做出来的东西

这一节里其实还提到了封装和继承的概念

封装,以前的我理解为封装就是将类里的字段对外隐藏,而其他类想要改变这些字段只能调用我的公共方法,而不可以直接修改。在读第二遍的时候,我发现封装的思想主要是为了隐藏自己内部的实现(内部实现不重要,重要的是对外提供的方法),保证了独立性。

继承就是通过扩展一些已有的类来构建新的类,而且新的类将会具有被扩展类的全部属性和方法,提高了重用性

2.使用预定义类

构造器

  • 用来构造并初始化对象的一种特殊的方法
  • 构造器的名字应该与类名相同

这里要明确一个东西,比方说,我定义了一个类叫做Animal,然后做了如下的操作

Animal mAnimal;

此时,mAnimal叫做对象变量,它是一个变量不是一个对象

然后做如下操作

mAnimal = new Animal();

此时mAnimal引用了一个对象

变量只能是引用对象

更改器方法和访问器方法

  • 更改器方法描述的是使用了方法之后,对象的状态会改变
  • 访问器方法描述的是使用了方法之后,对象的状态没有改变

3.用户自定义类

隐式参数与显示参数

一句话,隐式参数是调用方法的对象本身(在方法中可用this来表示),显示参数是方法名后面的数值

Java中4种访问修饰符

  • private:仅对本类可见
  • public:对外部完全可见
  • protected:对本包及所有子类可见
  • 默认(无需修饰符):对本包可见

4.静态字段和静态方法

静态字段

静态字段即用static修饰的字段,静态字段是属于,不属于单个任何对象的

静态方法

static修饰的方法,属于类,不属于对象,即在静态方法中不能使用this关键字(即,没有隐式参数),静态方法不能访问实例字段,但是可以访问静态字段

5.方法参数

跳过

6.对象构造

重载

  • 方法签名:通过指定方法名参数类型来描述一个方法
  • 重载即是出现了多个方法,有相同的名字,但是不同的参数,程序会在调用方法时根据参数类型来选择使用哪一个方法

调用构造器后的处理的优先级顺序

  1. 如果第一行调用了另一个构造器(使用this(...),另外,在构造器中调用另一个构造器这个语句也只能写在第一行),则执行另一个构造器
  2. 否则则先后执行:
    1. 静态字段
    2. 静态的初始化块
    3. 所有实例字段初始化为默认值(0,false,null)
    4. 初始化块
  3. 最后才是执行构造器主体代码

以前总弄不清静态字段还有静态代码块的执行顺序,今天读到这里,可谓天清地明

7.包

使用包来确保类名的唯一性

静态导入

第 5 章 继承

1.类,子类,超类

thissuper的含义

  • this
    • 一是指隐式参数的调用
    • 二是指调用该类的其他构造器
  • super
    • 一是调用超类的方法
    • 二 是调用超类的构造器

多态

一个对象变量可以指示多种实际类型的现象称为多态

替换原则:程序中出现超类对象的任何地方都可以使用子类对象替换。例如:可将子类对象赋给超类变量

重载解析:。。。

动态绑定与静态绑定:

  • 动态绑定:在运行时能够自动地选择恰当的方法(调用的方法依赖隐式参数的实际类型)
  • 静态绑定:用privatestaticfinal修饰的方法,编译器将准确的知道该调用哪个方法

强制类型转换

唯一原因:要在暂时忽视对象的实际类型之后使用对象的全部功能。

可用instanceof操作符来判断所属类型

抽象类

更具有一般性的,只用作派生其他类的基类,而不是用来构造实例的类

可以包含字段和具体方法

不能被实例化

2.Object:所有类的超类

Object类是Java中所有类的氏族,每个类都自动的继承自Object

在Java中,只有基本类型不是对象

4.对象包装器和自动装箱拆箱

对象包装器

因为基本类型不是对象,但有时候又需要把基本类型转换成对象来使用,所以就出现了对象包装器这个概念。

基本类型 对应的包装器类
int Integer
long Long
float Float
double Double
short Short
byte Byte
char Character
boolean Boolean

包装器类是final

自动装箱与自动拆箱

        List<Integer> list = new ArrayList<>();
        list.add(2);

如上面给出的例子,list添加一个元素的时候,元素类型本该是Integer类型,可是2只是个int类型,不过没关系,list.add(2)将自动的变成list.add(Integer.valueOf(2)),这种变换称为自动装箱

同样的,如果想将一个Integer对象赋给一个int值时,将会自动拆箱

第 6 章 接口,lambda表达式与内部类

1.接口

在Java程序设计语言中,接口不是类,而是对希望符合这个接口类的一组需求

接口中的所有方法都自动是public方法(但是实现接口时,必须把方法声明为public

接口中的字段总是public static final

接口绝不会有实例字段

接口同样不能被实例化,但是接口变量可以引用实现了这个接口的类对象

一个类只能有一个超类,但可以实现多个接口

2.lambda表达式

先跳过,看的云里雾里的@_@

3.内部类

定义在另一个类中的类

原因:

  • 内部类可以对同一包中的其他类隐藏
  • 内部类方法可以访问外部类的私有属性

常规内部类中可以有static字段(但也都必须是final),但是不能有static方法

局部内部类

在一个方法中局部地定义这个类

声明局部类时不能有访问说明符(public等)

对外界完全隐藏

静态内部类

内部类不需要访问外围类对象,就应该使用静态内部类

静态内部类可以有静态字段和静态方法

在接口中声明的内部类自动是staticpublic

第 7 章 异常,断言和日志

派生于Error类或RuntimeException类的所有异常称为非检查型异常

所有其他异常称为检查型异常

这一章的剩余部分先略过,先不看

第 8 章 泛型程序设计

泛型方法:可以在普通类型中定义,也可在泛型类中定义

public class ArrayAlg {
    public static <T> T getMiddle(T... a) {
        return a[a.length / 2];
    }
}

限定类型: 限定T只能是限定类型的子类型

<T extends Comparable>
<T extends Comparable & Serializable> //甚至是多个限定

类型擦除:指的是定义了一个泛型类型,都会自动提供一个相应的原始类型。(原始类型用第一个限定来替换类型变量,如无限定,则替换为Object类型)

通配符(?

<? extends Employee> //表示参数类型是Employee的子类
<? super Employee> //表示参数类型是Employee的超类

第 9 章 集合

集合类型 说明
ArrayList 可以动态增长和缩减空间的一个索引序列
LinkedList 链表,可在任何位置高效的插入和删除的一个有序序列

IteratorIterable

IteratorIterable都是接口

  • Iterator:迭代器,Java 1.2引入,用来代替 Enumeration的,通过hasNextnext方法可以逐个访问集合中的每个元素
  • Iterable:Java 1.5 引入,为的是Implementing this interface allows an object to be the target of the “for-each loop” statement.,也就是for each循环可以处理任何实现了Iterable接口的对象

第 12 章 并发

多线程:一个程序可以同时运行多个线程

多进程和多线程的区别:每个进程都拥有自己的一整套变量,而线程则共享数据

新建线程的两种方式

一:新建类实现Runnable接口(完成run方法),然后赋给一个Thread对象

    public static class MyRun implements Runnable {

        @Override
        public void run() {
            System.out.println("MyRun");
        }
    }
// 使用
        Runnable r = new MyRun();
        Thread thread1 = new Thread(r);
        thread1.start();

二:建立一个Thread的子类

    public static class MyThread extends Thread {

        @Override
        public void run() {
            super.run();
            System.out.println("MyThread");
        }
    }
// 使用
        Thread thread2 = new MyThread();
        thread2.start();

线程的状态

  • New:新建
  • Runnable:可运行(可能正在运行也可能没有运行)
  • Blocked:阻塞
  • Waiting:等待
  • Timed waiting:计时等待
  • Terminated:终止

synchronized关键字

从Java1.0版开始,Java中的每个对象都有一个内部锁。如果一个方法声明时有 synchronized 关键字,那么,要调用这个方法,线程必须获得内部对象锁

volatile修饰符:用来修饰字段,可以让多线程安全地读取一个字段