javaSE基础知识汇总
自动类型转换
自动类型转换:把一个表示数据范围小的数值或变量赋值给另一个表示数据范围大的变量。
强制类型转换:把一个表示数据范围大的数值或变量赋值给另一个表示数据范围小的变量。
- 基本数据类型(byte,short,int,long,float,double,char)的数据范围
- 注意:
-
字符“+”的操作:
算数表达式中包含多个基本数据类型的值的时候,整个算数表达式的类型会自动提升。 提升规则: 1. byte/short/char 将自动提升为 int。 如: byte num1=10; byte num2=20; int result = num1 + num2; // int result = (int)num1 + (int)num2 2. 整个表达式的类型自动提升到表达式中较大范围的类型 如: byte a = 10; long b = 20; long l = a + b; // long l = (long)a + (long)b
-
字符串“+”的操作:
连接运算符: 如:"你好" + 123。结果:"你好123" 算数运算符: 如:1 + 2 + "你好"。结果:"3你好"
-
赋值运算符隐含了强制类型转换
byte num =30; // byte + int --> (byte) (int + int) num += 5;
-
逻辑运算符
流程控制语句switch
switch (表达式) {
case 值1:
System.out.println("1");
break;
case 值2:
System.out.println("2");
break;
default:
System.out.println("2");
[break;]
}
- 表达式:
- 取值为byte,short,int,char
- JDK5以后可以是枚举
- JDK7以后可以是String
- switch穿透
switch (num) { case 1: case 2: // switch穿透 method1(); break; case 3: method(); return; // 直接结束当前方法 default: System.out.println("2"); break; }
基本类型及引用类型在数组或者对象中成员变量的默认值
内存介绍
-
内存图
-
字符串对象存在哪里?
以""方式给出的字符串对象,在字符串常量池中存储,而且相同内容只会在其中存储一份。
String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2); // true char[] chs = {'a','b','c'}; String s3 = new String(chs); String s4 = new String(chs); System.out.println(s3 == s4); // flase // 字符串内容比较使用equals,==比较的是地址 System.out.println(s3.equals(s4)); // true
-
垃圾回收
当堆内存总的类对象或数组对象,没有被任何变量引用(指向)时,就会被判定为内存中的“垃圾”。java存在自动垃圾回收器,会定期进行清理。
方法重载
- 只要
同一个类中,多个方法的名称相同,形参列表不同
,其他不管。(如:修饰符,返回值类型都无所谓) - 好处:可读性好,方法名称相同提示同一类型的功能,这是一种专业的代码设计。
return关键字单独使用
可以立即跳出并结束当前方法的执行。单独使用,可以使用在任何方法中。
类中的成分
- 类中可以定义5大成分:成员变量,构造器,成员方法,代码块,内部类
public class Person { // 成员变量 private String name; // 构造器 public Person() { } // 方法 public void run(){ } // 代码块 static { } // 内部类 public class Heart{ } }
代码块
- 静态代码块:static{},随着类的加载而加载,自动触发,只执行一次。
- 构造代码块:{},每次创建对象调用构造器时,会执行该代码块,并且在构造器执行前执行。
static关键字作用
static是静态的意思,可以修饰成员变量,表示该成员变量在内存中只存储一份,可以被共享访问,修改
。
访问:类名.静态成员变量
(推荐)
对象.静态成员变量 (不推荐)
工具类建议
- 对于一些应用程序中多次用到的功能,可以将这些功能封装成静态方法,放在一个类中,这个类就是工具类。
- 建议将功能类的构造器私有,不让工具类对外产生对象。
单例设计模式
- 饿汉单例设计模式:在用类获取对象的时候,对象已经提前为你创建好
- 懒汉单例设计模式:在真正需要该对象的时候,才去创建一个对象(延迟加载对象)
继承
- 方法重写@Override
注意: 1. 私有方法不能被重写 2. 子类不能重写父类的静态方法 3. 子类重写父类方法时,子类方法的访问权限必须>=父类
- 子类继承父类,构造器的特点
子类中所有的构造器,默认先访问父类中的无参构造器,再执行自己的构造器。子类构造器默认第一行语句:super()。 父类没有无参构造器,子类调用会报错,除非手动调用父类有参构造器,super(...)
权限修饰符
- 用来控制一个成员能够被访问的范围
- 可以修饰成员变量,成员方法,构造方法,内部类
- 作用范围从小到大:private > 缺省 > protected > piblic
枚举
抽象类
- 抽象类是用类被继承的,抽象方法是交给子类重写的
- 一个类如果继承了抽象类,那么这个类必须重写抽象类的所有抽象方法,否则这个类也必须定义为抽象类
- 模板方法:参考菜鸟教程
- 模板方法就是搭好了一个骨架,然后由不同的对象去填充。
- 模板方法建议使用final修饰。模板方法是给子类直接使用的,不是让子类重写的,一旦子类重写了模板方法就失效了。
接口
JDK8之前,接口中只能是抽象方法,常量,没有其他成分
JDK8,增加默认方法,静态方法
JDK9,私有方法
多态
概念:同类型的对象,执行同一个行为,会表现出不同的特征。
语法:父类类型 对象名称 = new 子类构造器
多态中成员访问特点:
- 方法调用:编译看左边,运行看右边
- 变量调用:编译看左边,运行看左边
(多态侧重行为多态)
避免类型转换异常,java建议强转前使用
变量名 instanceof 真实类型
判断当前对象的真实类型,再进行强转。
内部类
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整的结构又只为外部事物提供服务,那么整个内部的完整结构可以选择使用内部类设计。
-
静态成员内部类
-
成员内部类
-
匿名内部类
接口名 对象名 = new 接口名{ // 覆盖重写所有的抽象方法 };
常用api
-
Object类中常用api
这两个方法存在的意义就是被子类重写。 子类重写toString()以便返回对象的内容;子类重写equals()以便子类自己定制比较规则。 比如String类就重写了equals()
-
Objects类中常用api
-
StringBuilder
StringBuilder是一个可变的字符串类,可以把他看成一个容器。能提高字符串的操作效率,如拼接,修改等。
内存图
-
BigDecimal
System.out.println(0.01 + 0.09); // 0.09999999999999999 // 包装浮点型数据成为大数据对象的推荐两种方式 BigDecimal m = new BigDecimal("0.01"); BigDecimal n = BigDecimal.valueOf(0.09); double res = m.add(n).doubleValue(); // 0.1 System.out.println(res);
-
Arrays工具类
-
Collections工具类
集合
-
Collection单列集合
Collection接口 | |---List子接口:元素有索引,有序、元素可重复 | | | |---ArrayList实现类 | |---LinkedList实现类 |---Set子接口:元素无索引,无序(不是随机无序),不可重复 | |---HashSet实现类 | |---LinkedHashSet实现类
HashSet存储去重原理
-
Map双列集合
// HashMap是Map的实现类,特点由键决定:无序,不重复,无索引 // HashMap跟HashSet底层原理一致(都是哈希表结构,只是HashMap的每个元素包含两个值而已) // HashSet源码 public HashSet() { map = new HashMap<>(); }
-
循环遍历
Collection<String> list = new ArrayList(); // 迭代器 Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } // 增强for循环(内部是迭代器):用来遍历集合和数组 for (String s: list){ System.out.println(s); } // 内部仍是增强for循环 list.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } }); // 普通for循环,用来遍历含索引的集合和数组
增强for循环原理:
equals()和hashCode()的关系
Java设计的顶级父类Object类中,有两个方法很特殊,它们分别是equals方法与hashCode方法。当我们将equals方法重写后有必要将hashCode方法也重写,这样做才能保证不违背hashCode方法中“相同对象必须有相同哈希值”的约定。
Stream流
泛型
-
定义泛型
-
通配符?:
表示使用泛型
,代表一切类型
异常
-
异常分类
Throwable | |--Error | |--Exception | |--编译期异常,如ClassNotFoundException | |--RuntimeException
-
认识异常
-
编译期异常
编译期异常的作用:是担心程序员的技术不行,在编译阶段就报错,目的在于提醒不要出错。
-
RuntimeException
// 数组索引越界异常:ArrayIndexOutOfBoundsException int[] i = {}; System.out.println(i[0]); // 空指针异常:NullPointerException String name = null; System.out.println(name.length()); // 类型转换异常:ClassCastException Object age = 18; String a = (String) age; // 数学操作异常:ArithmeticException int c = 10/0; // 数字转换异常:NumberFormatException String num = "123a"; Integer.valueOf(num);
-
-
定位异常位置
-
异常的处理
最好的规范是:底层的异常抛出给最外层,最外层捕获异常。如下:
-
自定义异常
必要性:如果企业想通过异常的方式管理自己的某个业务问题,就需要自定义异常类了。
好处:使用异常机制管理业务问题,如提醒程序员注意。一旦出现bug,能用异常的形式清晰的指出异常的位置。
继承RuntimeException就运行异常,继承Exception就是编译异常。