0
点赞
收藏
分享

微信扫一扫

java基础知识细节总结

钵仔糕的波波仔 2022-03-11 阅读 101
java

java基础知识细节总结

1. 浮点数细节

double num1 = 2.7; 			//2.7
double num2 = 8.1 / 3;		//接近2.7的一个小数,而不是2.7

1. 判断num1和num2是否相等的方法
if(Math.abs(num1 - num2) < 0.00001){
	System.out.println("num1 == num2");
}

2. 自动类型转换细节

1. byte, short, char 他们三者可以计算,在计算时首先转换为int类型

2. char --> int --> long --> float --> double

3. byte --> short --> int --> long --> float --> double

3. 强制类型转换细节

1. 强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
int x = (int)10 * 3.5 + 6 * 1.5 // 错误
int y = (int)(10 * 3.5 + 6 * 1.5) // 正确

2. char类型可以保存int的常量值,但不能保存int的变量值,需要强转
char c1 = 100; //正确
int m = 100; //正确
char c2 = m; //错误
char c3 = (char)m; //错误

4. 算术运算符细节

1. % 取模运算符。本质: a % b = a - a / b * b;
10 % 3; // 1
-10 % 3; // -1
10 % -3; // 1
-10 % -3; // -1

2. % 运算符符号与被除数相同

5. 赋值运算符细节

1. 赋值运算符会进行类型转换
byte b = 3;
b += 2; // 等价于 b = (byte)(b + 2);
b = b + 2; // 错误

6. 三元运算符细节

1. 三元运算符可以转换为if--else语句
int res = a > b ? a++ : --b;
if(a > b) res = a++;
else res = --b;

2. 表达式1和表达式2要为可以赋给接受变量的类型(或可以自动转换)
int a = 3;
int b = 8;
int c = a > b ? 1.1 : 3.4; //错误
int c = a > b ? (int) 1.1 : (int) 3.4; //正确

7. 标识符的命名规则细节

1.26个英文字母大小写,0-9,_或$组成
2. 数字不可以开头
int 3ab = 1;//错误

3. 不可以使用关键字和保留字,但能包含关键字和保留字
4. Java中严格区分大小写,长度无限制
5. 标识符不能包含空格。
int a b = 90; // 错误

8. 位运算符细节

1. 任何运算都是按该值的补码来进行运算的
2. 正数的原码,补码,反码都是其本身
3. 负数的反码 = 原码符号位不变,其他位取反
4. 负数的补码 = 负数的反码 + 1

/**
-2的原码:10000000 00000000 00000000 00000010
-2的反码:11111111 11111111 11111111 11111101
-2的补码:11111111 11111111 11111111 11111110
~-2操作: 00000000 00000000 00000000 00000001 => 1
*/
~-2; // 1

5. 算术右移>>:低位溢出,符号位不变,并用符号位补溢出的高位
6. 算术左移<<: 符号位不变,低位补0
7. >>> 逻辑右移:低位溢出,高位补0

9. switch细节

1. 表达式数据类型,应和case后的常量类型一致,或者是可以自动转换成可以相互比较的类型,比如输入的是字符,而常量是int

2. switch(表达式)中表达式的返回值必须是:byte,short,int,char,enum[枚举],String

10. 作用域细节

1. 属性如果不赋值,有默认值,规则和数组一致。int 0, short 0, byte 0, long 0, float 0.0, double 0.0, char \u0000, boolean false, String null

2. 全局变量可以不赋值,直接使用,因为有默认值。局部变量必须赋值后才能使用,因为没有默认值。

3. 全局变量/属性可以加修饰符。局部变量不可以加修饰符

11. 构造器细节

1. 构造器没有返回值

2. 构造器的修饰符可以默认,也可以是public, protected, private

12. this关键字细节

1. this 关键字可以用来访问本类的属性、方法、构造器
2. this 用于区分当前类的属性和局部变量
3. 访问成员方法的语法:this.方法名(参数列表);
4. 访问构造器语法:this(参数列表);注意只能在构造器中使用
5. this不能在类定义的外部使用,只能在类定义的方法中使用

13. 访问修饰符细节

1. 公开级别:用public修饰,对外公开
2. 受保护级别:用protected修饰,对子类和同一个包中的类公开
3. 默认级别:没有修饰符号,向同一个包的类公开
4. 私有级别:用private修饰,只有类本身可以访问,不可对外公开

14. 继承的细节

1. 子类必须调用父类的构造器,完成父类的初始化
2. 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
3. super在使用时,必须放在构造器第一行(super只能在构造器中使用)
4. super()this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

15. 方法重写细节

1. 子类的方法的参数,方法名称,要和父类方法的参数,方法名称完全一样
2. 子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类
3. 子类方法不能缩小父类方法的访问权限

16. 多态细节

向上转型:
	1. 本质:父类的引用指向了子类的对象
	2. 语法:父类类型  引用名 = new 子类类型();
	3. 特点:编译类型看左边,运行类型看右边。可以调用父类中的所有成员(需遵守访问权限),不能调用子类中特有成员;最终运行效果看子类的具体实现!
	4. 属性没有重写一说,属性的值看编译类型;
	class Base {
		int count = 10;
	}
	
	class Sub extends Base {
		int count = 20;
	}
	
	Base base = new Sub();
	System.out.println(base.count); // 10

向下转型:
	1. 语法:子类类型  引用名 = (子类类型)父类引用;
	2. 只能强转父类的引用,不能强转父类的对象
	3. 要求父类的引用必须指向的是当前目标类型的对象
	4. 可以调用子类类型中所有的成员
	class Animal{}
	class Cat extends Animal{}
	class Dog extends Animal{}
	Animal animal = new Cat();
	Cat cat = (Cat) animal; // 对
	Dog dog = (Dog) animal; // 错

1. instanceOf比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型
2. java动态绑定机制
	1. 当调用对象方法的时候,该方法会和该对象内存地址/运行类型绑定
	2. 当调用对象属性时,没有动态绑定机制,哪里声明,那里使用 

17. 代码块细节

1. static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次,如果是普通代码块,每创建一个对象,就执行。
2. 创建一个对象时,在一个类调用顺序是:
	1. 调用静态代码块和静态属性初始化
	2. 调用普通代码块和普通属性的初始化
	3. 调用构造方法 
3. 构造方法的最前面其实隐含了super()和调用普通代码块
4. 创建一个类的子类时的调用顺序:
	1. 父类的静态代码块和静态属性
	2. 子类的静态代码块和静态属性
	3. 父类的普通代码块和普通属性初始化
	4. 父类的构造方法
	5. 子类的普通代码块和普通属性初始化
	6. 子类的构造方法 
5. 静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员

18. 接口的细节

1. 在jdk7.0前,接口里的所有方法都没有方法体,即都是抽象方法
2. jdk8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
3. 接口中所有的方法是public方法
4. 接口中的属性,只能是final的,而且是public static final修饰符
5. 接口的修饰符只能是public和默认的

19. 内部类细节

1. 局部内部类是定义在外部类的局部位置,比如方法中,并且有类名
	1. 可以直接访问外部类的所有成员,包含私有的
	2. 不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用fianl作用域的。但是可以使用fianl修饰,因为局部变量也可以使用fianl
	3. 作用域:仅仅在定义它的方法和代码块中
	4. 局部内部类---访问--->外部类的成员【访问方式:直接访问】
	5. 外部类---访问--->局部内部类的成员【访问方式:创建对象,再访问】
	6. 外部其他类---不能访问--->局部内部类(因为局部内部类地位是一个局部变量)
	7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类.this.成员)去访问
2. 成员内部类是定义在外部类的成员位置,并且没有static修饰
	1. 可以直接访问外部类的所有成员,包含私有的
	2. 可以添加任意访问修饰符(public, protected, 默认, private),因为它的地位就是一个成员。
	3. 成员内部类---访问--->外部类【访问方式:直接访问】
	4. 外部类---访问--->内部类【访问方式:创建对象,再访问】
	5. 外部其他类---访问--->成员内部类

20. 枚举细节

1. 枚举可以这样理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象。
2. 不需要setXXX方法,因为枚举对象值通常为只读
3. 对枚举对象/属性使用final+static共同修饰,实现底层优化
4. 枚举对象名通常使用全部大写,常量的命名规范
5. 枚举对象根据需要,也可以有多个属性
6. 构造器私有化
7. 继承了Enum类

21. 异常细节

1. 异常事件的两大类
	1. Error(错误):如:JVM系统内部错误、资源耗尽等严重情况。
	2. Exception:如空指针访问,读取不存在的文件等。
		1. 运行时异常【程序运行时,发生的异常】
		2. 编译时异常【编程时,编译器检查出的异常】
2. 五大运行时异常:
	1. NullPointerException空指针异常
	2. ArithmeticException数学运算异常
	3. ArrayIndexOutOfBoundsException数组下标越界异常
	4. ClassCastException类型转换异常
	5. NumberFormatException数字格式不正确异常

22. 字符串细节

1. String
	1. String是final类,不能被其他的类继承
	2. String有属性private final char value[];用于存放字符串内容
	3. value是一个final类型,不可以修改:即value不能指向新地址,但是单个字符内容是可以变化
2. StringBuffer
	1. StringBuffer的直接父类是AbstractStringBuilder
	2. 在父类中AbstractStringBuilder有属性char[] value, 不是fianl
	3. StringBuffer是一个fianl类,不能被继承
	4. 效率高于String
3. StringBuilder
	1. StringBuilder的直接父类是AbstractStringBuilder
	2. StringBuiler是一个fianl类,不能被继承
	3. StringBuilder的方法,没有做互斥的处理,即没有synchronized关键字,因此在单线程的情况下使用

23. 集合

1. Collection接口和Map接口
	1. Collection接口的子接口:List实现类:ArrayList, LinkedList,Vector等
	2. Collection接口的子接口:Set实现类:HashSet,LinkedHashSet等
	3. Collection接口的子类都可以使用Iterator来进行遍历
	4. Map接口的实现类:HashMap,Hashtable等
	5. Map的key和value都可以是null,但key只能有一个null
2. ArrayList底层原理
	1. ArrayList维护了一个Object类型的数组elementData. transient Object[] elementData
	2. 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.53. 如果使用的指定大小的构造器,则初始化elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.53. LinkedList底层原理
	1. LinkedList底层实现了双向链表和双端队列的特点
	2. 可以添加任意元素(元素可以重复),包括null
	3. 线程不安全,没有实现同步
4. HashSet底层原理
	1. HashSet实际上是HashMap
	2. HashSet可以存放null,但是只能存放一个
	3. 添加元素时,先得到hash值,后将其转换成索引值,找到存储表table,看这个索引位置是否已经存放的有元素,如果没有直接加入,如果有调用equals比较,如果相同放弃添加,如果不相同添加到最后。如果一条链表的元素个数超过一定个数(默认是8),则将其进行红黑树变化。
5. LinkedHashSet底层原理
	1. LinkedHashSet是HashSet的子类
	2. LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表
	3. LinkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的 
6. HashMap底层原理
	1. HashMap底层是(数组+链表+红黑树)

24. 泛型细节

1. 泛型默认是Object。如:ArrayList arrayList = new ArrayList();<==>ArrayList<Object> arrayList = new ArrayList<Object>();
2. 静态方法中不能使用泛型
3. 泛型接口的类型,在继承接口或者实现接口时确定
4. 泛型方法:public<T, R> void fly(T t, R r){}

25. 线程细节

1. yield:线程的礼让。让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定礼让成功。
2. join:线程的插队。插队的线程一旦插队成功,则肯定先执行插入的线程的所有的任务。
3. 守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束。常见的守护线程:垃圾回收机制。
4. 同步方法(非静态的)的锁可以是this,也可以是其他对象
5. 同步方法(静态的)的锁为当前类本身
6. 下面操作会释放锁:
	1. 当前线程的同步方法、同步代码块执行结束
	2. 当前线程在同步代码块、同步方法中遇到breakreturn
	3. 当前同步代码块、同步方法中出现了未处理的Error或Exception
	4. 当前同步代码块、同步方法中执行了wait()方法
7. 下面操作不会释放锁:
	1. 线程执行同步代码块或同步方法时,程序调用Thread.sleep(),Thread.yield()方法暂停当前的线程的执行,不会释放锁
	2. 线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁

26. 流细节

1. 序列化对象时,默认将里面所有属性都进行序列化,但除了statictransient修饰的成员
2. 序列化对象时,要求里面属性的类型也需要实现序列化接口

27. 正则表达式

content = "2022年我正在看java基础学习视频";
String regStr = "\\d\\d\\d\\d"; // 匹配任意四个数字
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while(matcher.find()){
	System.out.println(matcher.group[0]);
}
/**
* matcher.find()原理分析:
* 	1. 根据指定的规则,定位满足规则的字符串
*  	2. 找到后,将子字符串的开始的索引记录到matcher对象的属性int[] groups;
* 		groups[0]=0, 把该子字符串的结束的索引+1的值记录到groups[1]=4
* 	3. 同时记录oldLast的值为字符串的结束的索引+1的值即4,即下次执行find时,从4开始匹配
* matcher.group[0]原理分析:
* 	1. 根据groups[0]=0和groups[1]=4的记录的位置,从content开始截取子字符串返回
*/
举报

相关推荐

0 条评论