关注公众号【爱做梦的锤子】后台回复【java知识点】可下载整理好的xmind思维导图
基础知识
基本数据类型
8种基本数据类型
-
字符型
- char-1
-
布尔型
- boolean-1
-
数值(符号位,一个字节=8位)
byte-1
short-2
int-4
long-8
float-4
double-8
浮点型
- 一种对实数的近似值的表现法,由一个有效数字加上幂数来表示,
自动拆装箱
自带拆装箱
-
基本数据类型
- 不需要new,在栈内存存储,比较高效
-
包装类型
- 基本数据类型不是面向对象的,Java语言在设计时,添加基本数据类型对应的包装类型
-
装箱
- 基本数据类型->包装类型【通过Integer.valueOf() 以int为例】
-
拆箱
- 包装类型->基本数据类型 【通过integer.intValue 以Integer为例】
Java5开始提供自动拆装箱
-
缺点
包装对象的数值比较不能简单的使用==
自动拆箱时会可能引发NPE
for循环中如果存在大量的拆装箱,会浪费资源
缓存机制
-
Integer的缓存机制
Java5新增功能,节省内存,提高性能
整型对象通过使用相同的对象引用实现了缓存和重用
整数区间在-128-127之间数值适用,最大值127可以通过-XX:AutoBoxCacheMax=size修改
自动装箱适用
-
其他缓存(通过包装成a,b两个对象时,可以使用a==b判断其是否相等)
-128至127之间的整数(§3.10.1)
true 和 false的布尔值 (§3.10.3)
‘\u0000’至 ‘\u007f’之间的字符(§3.10.4)
Byte, Short, Long有固定范围: -128 到 127。对于Character, 范围是 0 到 127。除了Integer以外,这个范围都不能改变。
String
不可变性
- 一个String对象在内存堆中被创建出来,他就无法被修改
Java6与Java7的substring
- java6,导致问题:在一个很长的字符串中截取较短的一部分,会导致这个较长的字符串不能被回收,致使内存泄露,已被官方标记为JDK6的BUG
//JDK 6
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public String substring(int beginIndex, int endIndex) {
//check boundary
return new String(offset + beginIndex, endIndex - beginIndex, value);
}
- java7
//JDK 7
public String(char value[], int offset, int count) {
//check boundary
this.value = Arrays.copyOfRange(value, offset, offset + count);
}
public String substring(int beginIndex, int endIndex) {
//check boundary
int subLen = endIndex - beginIndex;
return new String(value, beginIndex, subLen);
}
replaceFirst、replaceAll、replace区别
replaceFirst:基于正则表达式的匹配替换,只替换匹配到的第一个
replaceAll:基于正则表达式的匹配替换,替换全部符合规则的字符和字符串
replace:可以支持字符的替换,也支持字符串的替换,替换全部匹配的字符和字符串
字符串的拼接
-
concat拼接
- 生成一个新的字符串
-
+ 拼接
- 语法糖,实际上还是使用的时StringBuilder的append方法
-
StringBuffer
- 线程安全,append方法使用synchronized 修饰
StringBuilder
Java8中String.join方法
-
5中方式拼接相同字符串,耗时
- StringBuilder<StringBuffer<concat<+<StringUtils.join
String.valueOf和Integer.toString的区别
- 无区别,String.valueOf是通过调用Integer.toString实现
switch支持
java7开始switch支持String
switch支持int,直接通过比较int的值
switch支持char,将char字符转换成对应的asii码的数值,再进行比较
switch支持String,使用String的hashCode,以及equals方法来匹配
String str = "world";
String s;
switch((s = str).hashCode())
{
default:
break;
case 99162322:
if(s.equals("hello"))
System.out.println("hello");
break;
case 113318802:
if(s.equals("world"))
System.out.println("world");
break;
}
字符串池
字符串池是由String类私有的维护,是为了提升性能和减少内存开销,避免字符串的重复创建
-
字符串创建方式
直接使用字符串赋值。直接去字符串池中查找当前字符串值是否存在,存在,则直接将池中引用返回;如果不存在,则在字符串池中创建对象,然后将池中引用返回
显式new String()。首先会去字符串池中查找当前字符串值是否存在,如果不存在,则在字符串池中创建对象,存在则不创建。最后还要在堆中额外创建一个字符串对象,最后是将堆中对象的引用返回
-
回收机制
- new关键字创建的字符串对象如果不可达就会被gc回收。而字符串字面量创建的字符串对象,因为常量池中还持有对该字符串的引用,则不会被回收。这并不代表字符串池中的字符串永远不被回收,字符串池提供有GC相关接口,根据不同的GC策略,会在适当的时候回收
常量池
-
运行时常量池
属于方法区的一部分
Java并不要求常量都必须在编译期产生,运行期也可以产生新的常量,这些新的常量就被放在运行时常量池中
-
class常量池
- class文件结构
class文件最前的四个字节,用于存储Magic Number,来确定这个class文件是否能够被这个虚拟机所接受。接下来的4个字节用来存储版本号,前两个字节存储次版本号,后两个字节存储主版本号。在这之后就是常量池的入口,开始的两个字节为常量池容量计数器,记录常量池中常量数量
* class常量池是class文件的资源仓库
字面量:Java语言层面常量的概念,如文本字符串,声明为final的常量值
符号引用量: 类和接口的 全限定 名、 字段名称和描述符、方法名称和描述符
intern
intern() 方法返回字符串对象的规范化表示形式
”string”.intern()方法的时候会返回”string”,但是这个方法会首先检查字符串池中是否有”string”这个字符串,如果存在则返回这个字符串的引用,否则就将这个字符串添加到字符串池中,然会返回这个字符串的引用
Java关键字
transient
表示变量不被序列化处理
-
序列化
- 序列化即对一个对象进行持久化处理,将对象转换成字节流进行存储和传输
-
反序列化
- 将一个序列化后的对象字节流转换成其对应对象是反序列化
instanceof
-
Java中的一个双目运算符,用来测试一个对象是否是属于某一个类的实例
当该对象是属于该类创建的实例时返回 true
当该对象不属于该类所创建的实例时返回 false
volatile
-
可见性
- 可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。
-
问题
- 在多线程操作同一个变量时,实际上是在每个线程中开启一块缓存,将该变量的值复制一份,缓存在当前线程缓存中,这就无法确保执行读操作的线程能实时地看到其他线程写入的值
-
作用
- 被volatile修饰的变量,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,且各个线程每次使用前都立即从主内存刷新,即可实时看到其他线程实时更新值
synchronized
同步方法或同步代码块
synchronized取得的锁都是对象锁,synchronized块之间具有互斥性,支持重入,不保证公平性,等待线程采用竞争方式获取锁,发生异常时会自动释放锁
final
-
修饰类
该类不能被继承
类中成员变量,可以自行设置是否为final
类中成员方法隐式为final
-
修饰方法
- 该方法不能被重写
-
修饰变量
必须初始化
初始化后不可更改
static
-
修饰内部类
- 内部类可直接通过外部类的类名调用,不用需要创建外部类实例来调用
-
修饰方法
- 该方法从属于该类,可以使用类名之间调用
-
修饰变量
- 静态变量,属于该类
-
修饰代码块
- 类被加载时,该代码块会被执行一次
const
- const是java中的预留关键字