【Java】Java基础知识及其扩展笔记(8千字)



学习教程: [Java基础知识]

零 l  写在前面


1、对“Java基础知识”中的一些扩展,有意思的文中和文外内容都会记录下来。




一 l  JVM


1、【1.1.2.1】java程序运行的一般流程

.java源代码文件 ——JDK中的javac粗编译——》.class字节码文件 ——JVM解释或编译——》二进制机器码

2、【1.1.2.1】JVM一般运行流程

读取.class字节码文件,使用解释器逐行解释执行

3、【1.1.2.1】JIT(just in time 即时编译编译器)

JIT是JVM的一部分,使用编译的方式提高JVM执行代码的速度。
当某行代码或某个函数调用次数过多(已经执行很多次后),JVM会使用JIT将.class中的对应代码块进行编译,下次直接使用编译后的文件。

如果某次循环的时候JIT遍历的循环内的代码块,则下次执行时优先使用编译后的二进制文件,而不会进行逐行解释。
 
扩展链接:深入浅出 JIT 编译器及其优化策略
JIT优化策略概括来说就是:选择合适的编译模式(client/server)、提高编译后代码的存储空间、调整编译阈值、调整编译线程数

4、堆与栈

简单来说

 
访问速度
空间大(理论上可以使用全部虚拟内存)
对应变量(一般情况)没有new的变量new的变量
例子简单类型、数组或对象的引用new的一个类、String常量池

对于 String数组 ,如果 不new 则数组实体指向 栈的常量池(指向的是个地址,但是这个常量池地址在堆)new 的话数组实体在
其他类型数组 无论是否new ,数组引用都在栈,数组实体都在堆

在如下代码中,user是User类实例的一个引用,所以在栈里;user指向的User实例是new出来的,所以在堆里。

User user = new User();

扩展链接[堆栈的详细区别]





二 l  Java 基础


1、【1.1.4】Java的类不能多继承,接口可以

2、【1.1.4】Java的字符串有length()方法得到长度,所以不用在最后加上’\0’结束符

3、【1.1.7】java的包和javax的包没有差别

4、【1.2.1】变量空间

基本类型含义大小默认值最小值最大值包装类型包装类型常量池大小
boolean布尔类型数组中1byte / 单个变量4bytefalsefalsetrueBooleantrue/false
char单个字符2byte / 16bits‘u0000’0216-1Character[0, 127]
byte字节整形1byte / 8bits0-128127Byte[-128, 127]
short短整形2byte / 16bits0-215 / -32768215-1 / 32767Short[-128, 127]
int整形4byte / 32bits0-231 / 约-2.1*109231-1 / 约2.1*109Integer[-128, 127]
long长整形8byte / 64bits0L-263 / 约-9.2*1018263-1 / 约9.2*1018Long[-128, 127]
float单精度浮点数4byte / 32bits0fIEEE754IEEE754Float
double双精度浮点数8byte / 64bits0dIEEE754IEEE754Double
voidVoid

boolean的大小:在数组中为了存储方便,一般会转换成byte类型;在单个变量中为了比较方便,一般会转换成int类型

5、【1.2.4】关键字是特殊的标识符,标识符是变量、方法等的名字

常见的关键字(红色字体为容易忽略的内容):

方法: 表示实例方法和静态方法都可以使用
变量、类变量、引用变量: 都是变量,因为java中都是对象,所以变量都是类变量;变量的实质就是引用,所以又可以说是引用变量
成员变量: 定义在类内函数外的变量,默认自动赋默认值(final必须显式赋值)
局部变量: 定义在函数内的变量,不会自动赋值

关键字类型关键字约束范围解释
访问控制private成员变量 / 方法 / 类私有,不允许用在局部变量【允许访问修改范围:同一类内】
default默认的访问控制权限【允许访问修改范围:同一包内】
protected成员变量 / 方法 / 类保护,不允许用在局部变量【允许访问修改范围:同一包内、不同包的子类】
public成员变量 / 方法 / 类 / 接口公开,不允许用在局部变量【允许访问修改范围:所有地方】
类、
方法、
变量修饰符
class说明正在定义一个类
abstract限定这个类或方法是抽象的 [扩展链接:abstract详解]
extends子类继承一个父类,只能继承一个
interface接口说明正在定义一个接口
接口方法默认都是public abstract
接口变量默认都是public static final
[扩展链接:abstract与interface的区别]
implements说明此类实现了什么接口
final变量 / 方法 / 类引用为基本数据类型,该引用为常量无法修改。
引用为引用数据类型,引用指向地址不能更改,地址里的内容可以修改。
修饰方法时,方法可以被继承,不能被重写。
修饰类时,无法被继承。
【不常用】native方法JNI(Java Native Interface Java本地接口)
与c/c++联合开发时才会使用
new变量创建一个已定义的类实例 [扩展链接:new是如何实现的]
static成员变量 / 静态方法不允许用在局部变量,方便在没有创建对象的情况下来进行调用(方法/变量)
static不允许用来修饰局部变量
[扩展链接:Java中的static关键字解析]
【不常用】strictfp类 / 接口(strict float point 精确浮点),严格使用IEEE754定义进行计算
【常考】transient变量标识变量不会输入到流中(不能串行化),如网络流、文件流
synchronized方法 / 代码块在并行中同步方法或代码块(同一时间只能有一个线程调用)
[扩展链接:synchronized实现原理]
【常考】volatile保证可见性和一定的有序性,不能保证原子性
在JMM(Java内存模型中),如果一个线程先去写一个变量,然后一个线程去进行读取,那么写入操作肯定会先行发生于读操作
[扩展链接:volatile关键字解析]
程序控制break方法跳出最内层循环
continue方法省略循环体内的后续步骤,进入下一次循环
return方法直接结束方法
if、else方法判断语句 if {} else if {} else {}
switch、case、default方法跳转语句,常用来优化多重if else
switch(条件){case ...: break; case default: break;}
switch条件可以为byte、short、int、char、enum、String(JDK7)
do、while方法循环语句,do{干活}while(条件) 或 while(条件){干活}
for方法循环语句,for( 条件(略) ) {干活}
instanceof方法A instanceof B
判断A是否是B的类实例、子类、接口实现类(A能否转换为B)
是则返回true,否则返回false
(大白话就是A是不是跟B有关,且B比A的“大”)
错误处理try、
catch、
finally
方法错误处理,
try {干活}
catch(Exception e) {处理异常}
finally {无论是否异常都会执行的代码}
throw方法体程序员主动抛出的异常,示例:throw new NumberFormatException();
throws方法头定义方法时预先声明可能会抛出的异常
包相关package.java文件开头声明当前包路径
import.java文件开头导入依赖包
基本类型boolean、byte、char、short、int、long、float、double、
null、true、false
变量引用super类内使用父类的成员属性或者成员方法
(能否使用以属性或方法的访问控制关键字为准)
this类内使用当前实例的属性,示例:this.userName
void方法说明返回值为空
保留字goto、const不允许使用c/c++中的goto不在java中被允许;
c/c++中的const在java中为final关键字

默认类加载顺序:
——》父类static方法
——》子类static方法
——》父类参数初始化
——》父类无参构造器初始化
——》子类参数初始化
——》子类无参构造器初始化

扩展:某些关键字的具体使用范围

关键字使用范围

6、【1.2.7】泛型与类型擦除

(1)常用通配符:T、E、K、V、?

(2)泛型最大的作用是用来给编译器检查的,编译后(.class文件)中会将泛型替换为最接近的共同父类

(3).java文件中,子类重写父类的泛型方法。
    .class文件中,子类重载了父类的方法,同时将父类方法指向子类的方法,使其最终的结果与重写相同。

(4)泛型不能是基本数据类型,泛型最大的父类就是ObjectObject不能存储某个数,只能引用某个对象

(5)[扩展链接:Java泛型类型擦除以及类型擦除带来的问题]

7、【1.2.8】==与equals

 ==equals
基本数据类型比较值不能比较
引用数据类型比较地址没有重写equals方法:比较地址
重写equals方法:根据方法比较

注意:
String类型不new的时候是从常量池从取值的,所以地址一样。即a==b为true

String a = "aaa";
String b = "aaa";

8、【1.2.9】equals与hashcode

(1)equals和hashcode都是Object类的方法,所有的类都会带这两个方法

(2)对于复杂类的equals效率可能低,所以可以使用hashcode快速粗筛选
    示例:HashSet检查重复就是先使用hashcode再使用equals

(3)hashcode()一般将int类型的散列码后返回,默认是对堆上的对象生成尽量不相同的特殊值,所以重写了equals()也要重写hashcode(),不然内容相同的对象hashcode不同,容易出bug。(比如HashSet里面添加了两个有相同数据的对象)

(4)[扩展链接:hashCode()和equals()的若干问题解答]

9、【1.4.2】形参是传实参的值还是实参的引用

对于基本数据类型和对象,都是是传值,只不过对象传的是对象地址(可以看做是引用,本质上是传的地址值,还是传值)。
所以形参修改对象成员值,实参也会跟着改变,因为指向的都是同一个对象。但是形参改变对象引用不会影响实参所指的对象引用。

10、【1.4.4】浅拷贝、深拷贝

 浅拷贝深拷贝
基本数据类型传递值传递值
引用数据类型传递引用new一个新对象并拷贝所有内容

11、【2.4】接口、抽象类细化比较

接口是特殊的抽象类,所以更加严格

 接口抽象类
继承impelement 多继承entends 单继承
限定符public、protected、defaultpublic、protected、default
变量类型static final普通变量
方法声明抽象方法、
默认方法(JDK8)、静态方法(JDK8)、
私有方法(JDK9)、私有静态方法(JDK9)
抽象方法、非抽象方法
方法实现不允许允许
实现约束要实现所有方法不用实现所有方法

12、【2.5.1】String、StringBuffer、StringBuilder分析

 StringStringBufferStringBuilder
数据可变性不可变可变可变
线程安全性安全安全不安全
速度慢,要new个String对象快,比 StringBuffer 快10~15%
使用场景少量数据多线程大量数据单线程大量数据

String类的源码中,使用private final char value[]来存储数据

JDK9中使用private final byte value[]来存储数据
StringBuffer和StringBuilder都继承自AbstractStringBuilder

13、【2.5.2】Object 类的常见方法

方法类型具体定义解释
常用方法(可重写)public native int hashCode()返回当前对象的hash值
public boolean equals(Object obj)默认是比较两个对象的地址是否相同,String类重写了此方法用来比较字符串
public String toString()默认是返回类的名字@实例的哈希码的16进制字符串(默认返回地址)
System.out输出对象时默认调用类的toString方法
protected native Object clone() throws CloneNotSupportedException返回当前对象的深拷贝
常用方法(不可重写)public final native Class<?> getClass()返回当前对象的class对象
等待方法(不可重写)public final void wait() throws InterruptedException暂停线程执行并释放所占用的锁(sleep不会释放占用的锁),会一直等待直到唤醒
public final native void wait(long timeout) throws InterruptedException功能同上(timeout是等待时间)
public final void wait(long timeout, int nanos) throws InterruptedException功能同上(nanos表示更精确的等待时间(纳秒),范围0~999999)
唤醒方法(不可重写)public final native void notify()唤醒 一个 在此对象监视器(锁)上等待的线程
public final native void notifyAll()唤醒 所有 在此对象监视器(锁)上等待的线程
销毁方法(可重写)protected void finalize() throws Throwable { }实例被垃圾回收器回收时自动调用





三 l  Java 面向对象


Java性能差的主要原因不是因为Java是面向对象的语言,而是因为Java是半编译语言,编译出来的.class文件不是二进制文件,而是要继续编译或解释。

1、【2.2.2】继承tips

子类拥有父类所有的属性和方法(包含私有的内容),但是根据访问控制前缀来判断能否访问。

2、【2.2.3】多态tips

父类的引用指向子类的实例才叫多态,如List<Integer> list = new ArrayList<Integer>();
(此时的引用不能调用子类独有的方法,有重写方法会调用重写方法,类型转换回子类后可以调用子类独有的方法)




四 l  Java 核心技术


1、【3.1.1】Collections 工具类和 Arrays 工具类常见方法

要用的时候再查,直接看也记不住。
[扩展链接:Collections工具类和Arrays工具类常见方法]

2、【3.2.1】Java异常类层次结构图

3.1.1
Errors类程序无法处理的异常 ,碰到Error的时候虚拟机一般会直接终止线程。

Exceptions类程序可以处理的异常

Exceptions类下的Check Exceptions是编译的时候检查的异常,Uncheck Exceptions是运行时的异常

3、【3.2.3】try-catch-finally

注意:finally是在函数返回之前做的,所以会覆盖try或catch里面的return

建议:使用try-with-resources替代try-catch-finally

try-catch-finally写法:

//读取⽂本⽂件的内容
Scanner scanner = null;
try {
    scanner = new Scanner(new File("D://read.txt"));
    while (scanner.hasNext()) { System.out.println(scanner.nextLine()); }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}

try-with-resources写法 (需要类实现AutoCloseable接口)

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) { System.out.println(scanner.nextLine()); }
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

4、【3.3.1】程序、进程、线程

程序:在数据存储设备中的静态代码

进程:程序被操作系统载入到内存中运行

线程:共享进程资源的cpu最小执行单位
线程状态:[图片来源]3.3.1

5、【3.4】文件与I\O流

流分类:

流的流向操作单元流的角色划分
输入流字节流节点流
输出流字符流处理流

4个抽象基类:

InputStream:字节输入流
OutputStream:字节输出流
Reader:字符输入流
Writer:字符输出流

传输字符的时候为了防止乱码或转换问题,使用字符流;其他时候使用字节流。

操作对象字节输入流字节输出流字符输入流字符输出流
文件FileInputStreamFileOutputStreamFileReaderFileWriter
基本数据类型DataInputStreamDataOutputStream
数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
对象序列化操作ObjectInputStreamObjectOutputStream
缓冲控制BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
字节流转字符流InputStreamReaderOutputStreamWriter
打印控制printStreamprintWriter
管道操作
(不推荐在同一个线程中使用,容易死锁)
PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值