Java基础知识之笔记总结分享(超详细)

给大家分享一篇我之前在学习java过程中的关于java基础部分的笔记,比较详细,内容也比较多。 如有问题请指出以便修改,谢谢。 篇幅较长建议收藏浏览。

1 环境变量配置

JAVA_HOME:jdk路径
Path:要把jdk的bin目录路径,添加到path变量

2.八种数据基本类型

比较简单此处不单独罗列
引用数据类型:数组,类,接口
2.1 char :Unicode编码的字符,或字符的整数编码,必须用单引号
float默认值是0.0f;
double默认值是0.0d;
2.2基本类型字面值规则
1.整数字面值是int类型,如果右侧赋值超出int范围,需要做转型处理
2.byte,short,char 三种比int小的整数,在自身范围内可以直接赋值。
byte d=1+3 正确,1+3编译器会自动转成4
3.浮点数字面值是double;浮点数转成整数会直接舍弃小数点后位数。
4.字面值后缀,L D F
5.字面值前缀,0b 二进制;0x 16进制;0 8进制; \u char 类型16进制
2.3基本类型的运算规则
1.计算结果的数据类型与运算中的最大类型一致。
2.byte,short,char三种比int小的整数,计算时会自动转成int
做加法运算时,数据类型会自动转成int,除了自增加自减不进行转化外,其它情况都是无long型时,所有非int类型转成int类型;有long类型时,都转成long类型。
char类型相加,提升为int类型。
Java基础知识之笔记总结分享(超详细)_第1张图片
3.整数运算溢出。Integer.MAX_VALUE+1 得负数最小值
4.浮点数运算不精确
5.浮点数特殊值 infinity 整数除0 ;Nan 负数开方
2.4 基本类型的类型转换
数字类型之间可以互相转换,从小到大自动转换,从大到小需要强制转型。
double d = 245; float d=100;自动转型
Java基础知识之笔记总结分享(超详细)_第2张图片
2.5运算符
&& :逻辑与(短路与),两边同为真结果才为真,短路与:左边是假,右边忽略不执行
& :不管左边结果是什么都要执行右边(&的左右两边都要参与运算)
|| :逻辑或(短路或),两边只要有一个真结果就是真,短路或:左边是真,右边忽略不执行

3.流程控制

3.1 switch:只能判断byte short char int enum jdk1.7之后的string。
从成立的case 无条件穿透所有的case包括default直到结束或者遇到break中断跳出循环;
如果所有条件都不成立,则执行default

3.2 for循环
在这里插入图片描述
3.3 break 和 continue
Break 中断、跳出循环和switch
Continue 跳过后面的代码 继续进入循环的下一轮执行
3.4 for-each循环
数组遍历、集合迭代遍历的语法简化
Java基础知识之笔记总结分享(超详细)_第3张图片
Java基础知识之笔记总结分享(超详细)_第4张图片

4.面向对象 —— 封装、继承、多态 ★ ★ ★ ★ ★

封装
1 类:模板、图纸 。类中定义对象的属性数据(成员变量),方法(成员方法)
类第一次使用时会加载到方法区
2 对象:从模板中创建的具体实例,实例是数据的打包
新建实例时,在堆内存中新分配内存空间给这个实例
Java基础知识之笔记总结分享(超详细)_第5张图片
3引用变量:理解成“遥控器”,保存一个实例的内存地址(引用变量保存在栈),引用变量的特殊值:null 不保存任何实例的内存地址
Java基础知识之笔记总结分享(超详细)_第6张图片
4构造方法:新建实例对象时,立即执行的一个特殊方法;构造方法必须和类同名,并且没有返回值类型。
一个类中必须有构造方法,自己没定义,系统会添加默认构造方法,构造方法一般用来给属性赋值
5 构造方法重载
一个类中可以定义多个不同参数的构造方法,是方法重载的一种体现
Java基础知识之笔记总结分享(超详细)_第7张图片
6 方法重载Overload:同名不同参,与返回值类型无关,所有方法都可以重载
7 this关键字:this.xxx 特殊引用,引用当前对象的地址
this(…):构造方法之间的调用,必须是首行代码,如果有多个构造方法,会通过this(…)调取下面的所有构造方法,完成赋值。
注意this不能在静态方法中使用
继承
Java的继承是单继承多实现,只能继承一个父类(如果不继承其他类,默认继承object类),但可以实现多个接口
1.不能继承的有:构造方法,私有成员
过程:先新建父类对象,再新建子类对象,两者作为一个整体对象,调用成员时,先找子类,再找父类
2.方法重写:override
继承的方法,在子类中重新定义父类中的方法(只能在子类重写),方法名相同,参数的个数和类型也必须相同,返回值类型也必须相同。
方法重写返回值类型如果是基本类型应与父类的一致;重写要求方法名完全相同,返回值类型如果是基本类型或无返回值时必须一致。
3.父类的构造方法
新建子类对象时会先新建父类对象,也会先执行父类的构造方法
默认执行父类的无参构造,默认隐含调用super();
new Student() 默认执行父类无参构造
new Student(……)默认执行父类无参构造
手动调用父类的有参构造,super(参数):父类没有无参构造时必须手动调用
4.super
Super.xxxx() 方法重写时,调用父类中同一个方法的代码
Super(参数) 调用父类的构造方法,默认调用父类无参构造super(),手动调用有参构造super(),必须是首行代码
注意super不能在静态方法中使用
多态
一个对象具有多种形态的表现,多态的前提是必须有继承。
void f(父类型 o1) { }
把一个子类型的实例当做父类型来处理,所有的子类型都可以传递到该方法,被当做父类型处理;作用:一致的类型
1. 类型的转换
A. 向上转型
子类的实例转成父类型,用父类型的引用变量,来引用子类实例,向上转型后,只能调用父类定义的通用成员,子类特有成员被隐藏
B. 向下转型
已经转成父类型的子类实例,转回子类型为了对子类型进行特殊处理
2. Instanceof 运行期类型识别
当多种子类型都被当做父类型来处理,要对某种子类型进行特殊处理,可以先判断其真实类型再向下转型——对真实类型,及其父类型判断,都返回true。格式:

s instanceof Line   

5.数组

属于object类,用来存放一组数据的数据结构,数组是最基本的一种数据结构但不是基本数据类型,数组是相同数据类型组成的集合,数组中的元素按线性顺序排序
1 数组的创建
数组创建后若未指定初始值,则会依据数组类型的不同来设置默认值

int[] a = new int[6];

新建int[]数组,长度6,默认值都是0,数组的起始地址值保存在变量a。

int[] a = {6,2,6,8};
Int[] a= new int[]{1,2,3,4,5};
a = new int[]{7,3,8,1,7,9,3,1};
 为存在的数组变量赋值直接初始化数据,要添加数据类型

2 数组的长度属性 a.length
数组一旦创立,长度不可变
最大下标 a.length-1
允许0长度的数组
3 二维数组
存放数组的数组

int[][] a = new int[3][2];

外围长度为3,内部3个数组长度为2,一共有4个数组,内部数组默认值0,外围数组保存的是内部数组的地址。

int[][] a = new int[3][];

只建一个外围数组长度3,3个位置都是null,之后可以建新数组放入内部。

4 Arrays 数组工具类

  • Arrays.toString(数组) 把数组数据连接成字符串。
  • Arrays.sort(数组) 数组排序 基本类型:优化的快速排序;引用类型:优化的合并排序。
  • Arrays.binarySearch(数组,目标值) 二分法查找,在有序数组中查找目标值下标,找不到返回 -(插入点+1)。
  • Arrays.copyof(数组,长度) 复制数组成一个指定长度的新数组。
    5 数组 复制
  • Arrays.copyof(数组,长度) 复制数组成一个指定长度的新数组
  • System.arraycopy(原数组,原数组起始位置,目标数组,目标数组起始位置,复制的数量) ——不会创建新的数组,目标数组要事先存在。

6. 变量

1 局部变量:定义在方法中或局部代码块中,必须初始化(第一次赋值时分配内存空间)
局部变量的作用域在定义它的大括号内有效,在作用范围内不能重复定义。
2 成员变量:定义在类中,自动初始化默认值,访问受访问控制符限制;局部变量可以和成员变量同名。

7.Object类

如果一个类不继承其他类,则默认继承Object类
1.方法
toString()获得一个对象的字符串表示。
Object中的默认实现是:“类名@地址”可在子类中重写toString方法。
equals() 当前对象与参与对象比较是否相等。
a.equals(b) Object中的默认实现是比较内存地址。
this == obj:==
Object中比较内存地址,基本类型默认比较内容值。

8.String 类

String是封装char[] 数组的对象

S =”abcd”
S={	-value:[‘a’,’b’,’d’,’g’]}

1.字符串创建

Char[] a ={‘a’,’b’,’c’};
String s = new String(a);  >>>简易语法>>> String s = “abcd”

2.字符串的常量池
String s1 = “abcd” 字符串的字面值写法。第一次使用一个字符串字面值时,会在字符串常量池中新分配内存,再次使用相同字面值时,直接访问常量池中存在的对象,而不会重复创建
3.字符串 中的Equals 和 “==”
“==”比较内存地址
Equals 看父类中的方法,object中的默认方法是比较内存地址,String类中重写了父类方法比较的是字符内容。如下说明:

char[] a = {'a','b','c','d'};
String s1 = new String(a);//堆中新分配内存
String s2 = "abcd"; //在常量池新分配内存
String s3 = "abcd"; //访问常量池中存在的对象
System.out.println(s1==s2); //false 比较内存地址
System.out.println(s2==s3); //true 比较内存地址
String类中重写了equals方法,方法中比较的是字符内容
System.out.println(s1.equals(s2));//true 比较字符串内容
System.out.println(s2.equals(s3));//true 比较字符串内容

4.字符串不可变且字符串连接效率低,每次连接都会新建字符串对象
5.字符串的常用方法

  • charAt(i) 获取指定位置的字符
  • length() 字符串长度,字符的数量
  • indexof()找第一个子串出现的初始位置,找不到返回-1
  • indexof(子串,start)从执行位置向后找
  • lastIndexof(子串) 从后向前找
  • subString(start)截取start到末尾
  • subString[start,end )截取[start,end )范围
  • trim()去除两端的空白字符
  • matches()用来判断是否匹配正则表达式

6.StringBuilder: 可变的字符序列,封装char[]数组,提供了一组方法,可以对内部封装的字符进行修改,常用来代替字符串做高效的字符串连接

  • append() 追加字符内容,内部数组默认初始容量16,放满后翻倍+2;
  • delete(start,end) 删除区间(start,end);
  • deleteCharAt(i)删除指定位置 i;
  • insert(i,内容) 在指定位置插入内容;
  • insertCharAt(i,字符)在指定位置插入单个字符;
  • replace(start,end,内容)替换指定范围的内容;
    StringBuilder和StringBuffer
    StringBuilder:线程不安全,效率高;JDK1.5版本后的新类。
    StringBuffer:线程安全,旧版本的类。

9.正则表达式

一般用来判断用户的输入内容是否符合格式要求

  • matches()字符串的方法,用来判断是否匹配
    if(s.matches(regex)) {}
  • split(正则):用匹配的子串来拆分字符串
    String s = "aaa,bbb,ccc";
    String[] a = s.split(",");
  • replace(正则,子串)替换所有匹配的子串

10.基本类型的包装类

把基本类型当做对象来使用
byte – Byte
short – Short
int – Integer
long – Long
float – Float
double – Double
char – Character
boolean – Boolean

1. 数字父类Number
子类:Byte,Short,Integer,Long,Float,Double,BigDecimal,BigInteger
取出基本类型值的方法
byteValue(),shortValue(),intValue(),longValue(),floatValue(),doubleValu()
2. Intger类
创建Integer对象: a= { value:6}
Integer a = new Integer(6);
Integer a = Integer.valueOf(6);
Integer 类中存在256个Integer缓存对象,封装-127到128;如果访问指定范围内的值,会访问缓存对象,如果超出范围,会新建对象。
3. Integer类的方法
字符串解析成int
Integer.parseInt();Byte.parseByte()……
Integer.toBinaryString() 转成二进制字符串
Integer.toOctalString() 转成八进制字符串
Integer.toHexString(255) 转成十六进制字符串
4. BigDcimal和BigInteger 类
BigDcimal精确的浮点数运算
BigInteger 超大的整数运算

创建对象:

BigDecimal bd = BigDecimal.valueOf(2);

方法:

  • add(BigDecimal bd)
  • subtract(BigDecimal bd)
  • multiply(BigDecimal bd)
  • divide(BigDecimal bd)
  • divide(BigDecimal bd,保留位数,舍入方式)
  • setScale(保留位数,舍入方式)

5. 自动装箱,自动拆箱
基本类型值,自动装箱成包装对象

Integer a = 6;    编译器编译成: Integer a = Integer.valueOf(6);

自动拆箱(自动拆箱要注意null值)

int i = a;    	 编译器编译成:		int i = a.intValue();

11.抽象类

半成品类,没有完成的类;抽象方法:没有代码,只有方法的定义,抽象类不能创建实例,主要用来被继承。

public abstract void f();

包含抽象方法的类一定是抽象类

public abstract class A { };

抽象方法的作用:
作为通用方法,在父类中定义;要求子类,必须实现这个方法。
1)抽象类可以有自己的构造方法
2)抽象类可以有具体的方法
3)包含抽象方法的类一定是抽象类,必须使用abstract关键字修饰,这个方法必须由子类来实现。
4)抽象类不能使用new关键字来创建实例
5)当一个类中只要有一个抽象方法,这个类就必须是抽象类
6)抽象类可以定义实例变量和静态变量以及常量
7)抽象类可以再继承抽象类,也可以继承普通的类

12.关键字 final

内存地址不可变,可以修饰常量、类、方法
1. final 常量:值不可变,但引用类型因为保存的是地址,所以内容可以变。
final Point a = new Point(3,4);
a.x = 30;//对
a.y = 40;//对
2. final 方法不能在子类重写,但可以被继承。;final不能用于修饰构造方法,父类的private成员方法是不能被子类方法覆盖的,因此private类型的方法默认是final类型的。
3. final 类 不能被继承,没有子类
Static — 静态 共享的数据
静态成员属于类,而不属于实例

  • 静态成员
    用类来调用静态成员 Soldier.count
  • 实例成员
    用实例来调用实例成员 s1.id
  • 工具方法
    Math.Random() Arrays.toString() String.valueOf()
    静态方法中不能直接调用实例的成员(非静态),只能用实例调用
class A {
public static void main(String[] args) {
    f();//静态调静态
}
static void f() {
   g();//错,静态不能直接调用非静态
    A a = new A();
    a.g();//只能用实例调用
}
void g(){
}
}

静态初始化块

class A {
static {
    静态初始化块
    类被加载时,只执行一次
}
}

静态变量保存在方法区类的空间中,只保存一份可以在所有实例中共享的数据
Java基础知识之笔记总结分享(超详细)_第8张图片
对象的加载过程
加载类
1.加载父类,为父类静态变量分配内存 – 后台执行不可见
2. 加载子类,为子类静态变量分配内存

3. 执行父类静态变量的赋值运算,和静态初始化块
4. 执行子类静态变量的赋值运算,和静态初始化块
新建实例
5. 新建父类实例,为父类实例变量分配内存
6. 新建子类实例,为子类实例变量分配内存

7. 执行父类的实例变量赋值运算
8. 执行父类的构造方法
9. 执行子类的实例变量赋值运算
10. 执行子类的构造方法

13.集合

用来存放一组数据的数据结构
数组的缺点: 长度固定 ; 访问方式单一只能下标访问; 前面增删数据操作繁琐
集合的继承结构:
Java基础知识之笔记总结分享(超详细)_第9张图片
Collection 是对象集合, Collection 有两个子接口 List 和 Set,
List 可以通过下标 (1,2…) 来取得值,值可以重复,而 Set 只能通过游标来取值,并且值是不能重复的
ArrayList , Vector , LinkedList 是 List 的实现类
ArrayList 是线程不安全的, Vector 是线程安全的,这两个类底层都是由数组实现的
LinkedList 是线程不安全的,底层是由链表实现的
Map 是键值对集合
HashTable 和 HashMap 是 Map 的实现类
HashTable 是线程安全的,不能存储 null 值
HashMap 不是线程安全的,可以存储 null 值
ArrayList
数组列表,封装了一个数组,及其操作代码和更便捷的方法,内部数组默认初始容量10 放满后,1.5倍增长
方法
add(数据)— 添加数据;get(int i)—访问指定下标数据; remove(int i)移除指定位置数据,返回被移除的数据; remove(数据)— 找到第一个相等的数据,找到移除并返回true,找不到返回false; size() 元素的数量;iterator() 辅助新建迭代器
效率
访问任意位置效率高,增删数据效率可能降低

LinkedList — 双向链表
方法
和ArrayList有相同的方法
LinkedList 两端数据操作方法
addFirst(数据);addLast(数据);getFirst();getLast();removeFisrt()
removeLast()
效率
两端效率高
HashMap — 哈希表、散列表 (面试必问) ★ ★ ★ ★ ★
存放键值对数据,用键来快速定位数据,来提取键对应的值
键:不重复,无序
Hashmap中的key-value都是储存中entry数组中的
Hashmap的实现不是同步的,意味着它不是线程安全的
Hashmap的实例有两个参数影响其性能:初始容量,和加载因子
方法
put(key,value)放入键值对数据,重复的键会覆盖旧值
get(key)获得键对应的值,键不存在,得到null
remove(key)移除键值对数据,返回被移除的值
size()键值对的数量

哈希运算过程

HashMap内部,使用entry[]数组存放数据
数组默认初始容量16
放满后容量翻倍+2

key.hashCode()获得键的哈希值
用哈希值和数组长度,运算产生下标值 i
新建entry对象来封装键值对数据
Entry对象,放入i 位置
	 如果是空位置,直接放入
	 如果有数据,一次equals()比较是否相等
		 找到相等的,覆盖旧值
		 没有相等的,链表连接在一起
	 负载率、加载因子超过0.75
		 新建翻倍容量的新数组
		 所有数据,重新执行哈希值,存入新数组
	 Jdk 1.8
		 链表长度到8,转成红黑树
		 树上的数据减少到6,转回成链表

hashCode()
hashCode()是object的方法,默认实现是用内存地址作为哈希值
可以重写方法来获得相同的哈希值
哈希运算中要有相同的哈希值,才能保证计算出相同下标值,并且要equals()也要相等(equals方法也要重写),才可以覆盖旧值,否则会链表连接。
重写hashCode的惯用算法:(x.y是变量的值)
x,y实例的变量值

14.异常

封装错误信息的对象
错误信息:类型、提示消息、行号
异常的继承结构
Java基础知识之笔记总结分享(超详细)_第10张图片
捕获异常

try {
} catch(AException e) {
} catch(BException e) {
} catch(父类型Exception e) {
} finally {
不管出不出错,都会执行
}
如果抛出异常,并且中catch中有return语句,这个return语句会先执行,执行之后将结果保
存在缓存中,再去查看是否有finally,如果有finally就先执行finally语句,之后再返回缓存中
return的值,如果finally中也有return,那么finally中的return会覆盖掉之前缓存中的return,
即最终会返回finally中的return值

throw 手动抛出异常,执行异常的抛出动作 类似 return;当程序出现逻辑错误,不自动创建并抛出异常,可以手动判断逻辑错误,手动创建异常对象并抛出。
底层的异常往上层抛,在上层处理

if(...) {
AException e = new AException();
throw e;
}

异常包装
捕获的异常对象,包装成其他类型再做抛出,多种类型简化成一种类型,不能抛出的异常包装成能抛出的异常再抛。
RuntimeException 和 其他Exception
RuntimeException— 非检查异常,编译器不检查是否有异常处理代码,存在默认的抛出管道
其他异常 — 编译器检查是否有处理代码,不处理,不能编译。

15.接口

极端的抽象类,结构设计工具,用来解耦合,隔离现实
Implements代替extends
Interface 代替class
接口的定义:
 公开的抽象方法  公开的常量  公开的内部类、内部接口
1)接口只能定义常量
2)接口只能定义抽象方法
3)接口只能继承接口,不能继承普通的类和抽象类
4)接口是没有构造方法
注意:
1)在接口中定义常量时,可以不用final static修饰,因为编译器在编译时会自动加上。
2)在接口中定义抽象方法时可以省略abstract关键字,编译器在编译时同样会加上。

类可以同时继承多个接口

class A implements X,Y,Z {}
class A extends B implements X,Y,Z {}

接口和接口的继承

interface A extends X,Y,Z {}

16.文件、字符操作流

File
封装一个磁盘路径字符串,提供了一组对文件、文件夹的操作方法,可以封装文件夹路径、文件路径、不存在的路径。 {path=“d:/abc”}
方法
getName() 获取文件名
getPatrent() 获取父目录
getAbsolutePath()完整路径
length() 文件字节量,对文件夹无效,会返回假数据
isFile() 判断是否是文件
isDirectory()是否是文件夹
创建、删除
createNewFile()新建文件,文件已存在不会新建,返回false;文件夹不存在会出现异常
mkdirs()逐层创建多层文件夹
delete()删除文件、空目录
目录列表
list()得到String[] 包含所有文件名 [“a.txt”, “b.mp3”, “c.jpg”]
listFiles() 得到 File[],包含所有文件的封装的File对象 [{…}, {…}, {…}]
流 Stream
数据的读写操作(io操作),抽象成数据在管道中流动
单方向流动
 输入流,只能用来读取数据(读入内存)
 输出流,只能用来输出数据(内存数据向外输出)
只能从头到尾,顺序流动一次,不能反复流动,如果要重复流动,可以重新创建新的流

InputStream,OutputStream
字节流的抽象父类
方法:
write(int b) 只输出int四个字节中,末尾的一个字节值 [1][2][3][4] —> [4]
write(byte[], start, length) 输出byte[] 数组中,从start开始的length个字节值
read() 读取一个字节值,补三个0字节,变成int [4] —> [1][2][3][4],读取结束后,再读取会返回 -1。
read(byte[] buff) 按数组的长度,读取一批字节值,存放到指定的数组中,并返回这一批的字节数量,读取结束后,再读取会返回 -1。
FileInputStream,FileOutputStream — 文件流
ObjectInputStream,ObjectOutputStream —对象序列化、反序列化
序列化 把一个对象的信息,按固定的字节格式,变成一串字节序列输出
在这里插入图片描述
方法:
writeObject(Object obj) 把对象变成一串字节序列输出
readObject() 读取序列化数据,反序列化恢复对象
Serializable 接口——被序列化的对象,必须实现 Serializable 接口
不序列化的变量
Static — 属于类,不随对象被序列化输出
Transient —临时,只在程序运行期间,在内存中存在,不会被序列化持久保存
字符编码
ASC-II 0到 127,英文、指令字符
iso-8859-1 Latin-1 西欧编码 ,把ASC-II扩展到255
CJK 编码 亚洲编码,中日韩
GBK 国标码 英文单字节,中文双字节
Unicode 万国码 常用表,双字节 生僻字 三字节或四字节
UTF-8 Unicode 的传输格式 Unicode Transformation format英文,单字节某些字符,双字节;中文,三字节;特殊符号,四字节
Java的char类型是 Unicode
Java的转码运算

Java基础知识之笔记总结分享(超详细)_第11张图片
InputStreamReader,OutputStreamWriter
字符编码转换流 OutputStreamWriter — 把Java的Unicode编码字符,转成其他编码输出
InputStreamReader —读取其他编码字符,转成Unicode字符

17.内部类

定义在类内部、方法内部或局部代码块内部的类,用来辅助外部实例运算,封装局部数据,或局部的运算逻辑。

非静态内部类、属于实例的内部类 非静态内部类实例,必须依赖于一个外部类的实例才能存在。
静态内部类 静态内部类,与普通的类没有区别。
局部内部类
局部定义的类型,类似于局部变量,有作用范围,只能在局部代码块内使用这种类型
局部内部类中,使用外面的局部变量,必须加 final,jdk1.8,缺省。
Java基础知识之笔记总结分享(超详细)_第12张图片
匿名内部类

Weapon w = new Weapon() {...};

 {} - 匿名类
 new - 新建匿名类的实例
 Weapon - 父类型
 () - super(),可传参数super(1,2,3)

18.Java内存管理

堆内存 用来存放由new创建的对象实例和数组。Java堆是所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例。注意创建出来的对象只包含属于各自的成员变量,并不包括成员方法。
栈内存 保存的是堆内存空间的访问地址,或者说栈中的变量指向堆内存中的变量(Java中的指针)
l 栈:保存局部变量的值,包括:1.用来保存基本数据类型的值;2.保存类的实例,即堆区对象的引用(指针)。也可以用来保存加载方法时的帧。常量池存在于堆中(1.7b后的新版本)。
普通类型的变量在栈中直接保存它所对应的值,而引用类型的变量保存的是一个指向堆区的指针,通过这个指针,就可以找到这个实例在堆区对应的对象。因此,普通类型变量只在栈区占用一块内存,而引用类型变量要在栈区和堆区各占一块内存。
方法区是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

19.线程

在进程内部,并行执行的任务
创建线程(两种方式)
 继承 Thread
 实现 Runnable
继承 Thread
编写 Thread 的子类,并重写 run() 方法。启动之后,自动运行 run() 方法中的代码
实现 Runnable
实现 Runnable 接口,实现它的 run() 方法,Runnable 封装在线程中执行的代码,新建线程对象时,把Runnable对象放在线程内,启动
线程的状态
Java基础知识之笔记总结分享(超详细)_第13张图片
线程的方法
Thread.currentThread() 获得正在执行的线程实例
Thread.sleep(毫秒值) 让正在执行的线程,暂停指定的毫秒值时长
getName(),setName() 线程名
start() 启动线程 interrupt() 打断线程的暂停状态
join() 当前线程暂停,等待被调用的线程结束
setDaemon(true) 后台线程、守护线程
JVM虚拟机退出条件,是所有前台线程结束,当所有前台线程结束,虚拟机会自动退出
不会等待后台线程结束 例如:垃圾回收器是一个后台线程。
线程同步 synchronized
让多个线程共享访问数据时,步调一致的执行。一个线程修改时,其他线程等待修改完成后才能执行;一个线程访问时,其他线程等待访问结束
任何实例,都有一个“同步锁”,synchronized 关键字,要求一个线程必须抢到同步锁才能执行

synchronized(对象) {
    共享的数据访问代码
} --抢对象的锁
synchronized void f() {
}  -- 抢当前实例的锁
static synchronized void f() {
}  --抢类的锁

生产者、消费者模型
线程之间传递数据
等待和通知方法必须在synchronized 代码内调用, 等待和通知的对象,必须是加锁的对象。

你可能感兴趣的:(知识总结)