引言
本文写作的目的是记录学习Java基础知识的过程中遇到的一些重要的知识点,这些知识点可以是API、死记硬背的东西、不经常出现但是对深入理解Java有很大帮助的话。我学习Java过程只参考,讲的很多东西都是实用的,但是相比于书本来说肯定是不够全面的。因此,在学习过程中需要经常思考,并且常看评论区,然后百度得到答案。
本文的笔记涉及的Java知识范围包括变量、操作符、控制流程、数组、类和接口、数字与字符串、日期
我距离第一次学完已经过了很长时间,也自己开发了Java系统,这个过程是对Java基础的温故知新。因此,现在正好有时间将我记录下的一些重要笔记发到博客中,希望能帮助到一些同样学习Java基础的人。在后面遇到新的东西也会经常来更新博客,大家有什么问题或新的见解可以在评论区回复。
1.下面列出了基本类型的数据范围,在IDE中给变量赋值超出范围会出现编译错误
3.整型变量都可以直接通过范围内的整数赋值,并支持各种进制;而浮点变量赋值默认为double,为float变量赋值必须在小数后加f
5.整型数据进行运算时,只要它们的类型<=int,结果就是一个int型;如果有long型变量,结果就是long
7.变量的作用域遵循就近原则,使用的是在可见范围内距离当前同名变量中最近的一个
8.因为整型数据是有正负的,所以除了无符号右移“>>>”外,其他的位操作符都可能得到负数,有符号右移“>>”会保留正负数属性。一个数乘以2的次幂,相当于这个数左移[次幂]位,例如a * 8 = a * 2^3,相当于a左移3位,这个特点在LeetCode题目中也会见到
9.使用Scanner读取用户输入的数据时,除了nextLine()会以回车作为结束符外,其余的都是以空白符为结束符。nextLine()会读取到残留的回车,因此需要用两次nextLine()来消除回车的影响。比如用户输入了两行数据:
12345
上山打老虎
第一行数据可以用一个int型变量来接收:int a = scanner.nextInt();
这时候就会残留一个回车和一段字符串,为了获取字符串,可以使用两次nextLine()函数:scanner.nextLine(); String str = scanner.nextLine();
第一次nextLine()得到一个回车符,第二次nextLine()才会得到完整的字符串(同时也包含了第二行的回车符)
10.switch支持byte、short、int、char、String、enum,其中判断String是通过hash实现的,可以理解为字面值,而不是引用
11.使用标签结束外部循环(注意冒号)
public class Main{
public static void main(String[] args){
out:
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++){
if (j % 2 == 0){
break out;
}
}
}
System.out.println("退出外部循环");
}
}
12.初始化一个数组可以使用arr = new int[length]或arr = new int[]{a,b,c}或arr = {a,b,c},第一种方式初始值全为0。如果指定了长度length就不能使用{}赋初值,只能在后续程序中一个个填充
13.Arrays类的静态方法:
int[] tmp = Arrays.copyOfRange(int[] original, int from, int to); /复制数组内容,to取不到
String content = Arrays.toString(a); //将数组a的内容转换为字符串
Arrays.sort(a); //对数组a进行排序(默认升)
Arrays.equals(a, b); //比较数组的内容是否一样,若比较数组是否一样用"=="
与第一个方法有相同作用的数组复制方法还有一个:System.arraycopy(src, srcPos, dest, destPos, length)
14.方法重载要求参数列表不同,包括数量、类型、顺序。可变数量的参数用三个点表示,必须放在列表最后,被当做数组使用
public void func(int a, double b, String...strings) {
for (int i = 0; i < strings.length; i++) {
System.out.println(strings[i]);
}
}
15.基本类型参数传递的是副本,而类参数传的是对象(不是引用)。修改了形参的指向,不会影响实参的指向;但修改对象的内容,两者指向的对象都会变化
16.类属性或方法用static声明,并且只能在static声明的方法中使用,例如Main函数。在一个静态方法内,不能使用非静态字段或非静态方法,因为它们都是跟对象关联的,没有对象就不能调用
17.属性的初始化有三种方式,分别是声明时赋值、块赋值、构造函数赋值。在程序运行时执行顺序是:静态赋值初始化、静态块初始化、普通赋值初始化、普通块初始化、普通构造函数初始化
public class Test{
private static int day = 7;
static {
System.out.println(day);
day = 6;
System.out.println(day);
}
private int month = 12;
{
month = 11;
}
public Test(){
month = 10;
}
public static void main(String[] args) {
Test test = new Test();
System.out.println(test.month);
System.out.println(Test.day);
}
}
// 输出7 6 10 6
18.单例模式:构造函数私有化、静态私有引用指向该类实例、提供一个静态公有方法获取该实例。单例模式有饿汉式和懒汉式,区别在于启动时,饿汉会加载实例,速度稍慢;懒汉式在第一次使用实例时才会创建
19.枚举类存放一些同类型的常量,全部大写并且用“,”分隔。这些常量对应的默认整数从0开始递增,可以用"V(num)"的形式定义常量V对应的整数,但是要在这个枚举类中定义一个编号变量(例如seq),并且提供构造函数和获取编号的方法(可选)
public enum Season {
SPRING(1),
SUMMER(2),
AUTUMN(4),
WINTER(8);
private int seq;
Season(int seq){
this.seq = seq;
}
public int getSeq() {
return this.seq;
}
}
20.ref instance of class:判断一个引用ref指向的对象是否属于class类或其子类
21.父类的非static方法可以被子类继承和重写,当一个父类引用指向子类对象并调用该方法时,会发挥子类重写后的作用;父类的static方法可以被子类继承或隐藏(重写的意思),当一个父类引用指向子类对象并调用该方法时,还是发挥父类的作用,但是一般不用对象来调用静态方法
// 父类
public class Animal {
public static void func1(){
System.out.println("父类静态方法");
}
public void func2(){
System.out.println("父类普通方法");
}
}
// 子类
public class Cat extends Animal{
public static void func1(){
System.out.println("子类静态方法");
}
@Override
public void func2(){
System.out.println("子类普通方法");
}
}
// 测试
public static void main(String[] args) {
Cat cat = new Cat();
Animal animal = cat;
animal.func2();
animal.func1();
}
// 输出
子类普通方法
父类静态方法
23.Object是所有类的父类,为所有类提供一些默认方法,可以直接重写:toString、finalize、equals、hashCode、wait、notify、notifyAll、getClass
24.Java抽象类可以对属性进行静态/非静态、final的定义,可以有非抽象方法并有方法体。接口可以有属性,但是它的属性必须是public static final定义并初始化的,也就是一个常量,默认方法可以有方法体,在方法最开头用default定义
25.内部类分为4种:非静态内部类、静态内部类、匿名类(常用)、本地类。前两个的定义与外部类的属性/方法等地位相同,可以理解为与外部类绑定在一起的有其他作用的类,两者的不同是静态类不需要外部类去实例化就可以调用;后两个是定义在方法中的,也就是什么时候要用某个类就什么时候定义,只不过匿名类没有名字,本地类有名字(在程序中直接写一个类的定义,并在之后进行实例化)。在匿名类或本地类中使用主程序中的变量时,主程序变量需要使用final定义
26.Java中跨系统的换行符“%n”
27.字符的一些方法:
Character.isLetter(c) //是否为字母
Character.isDigit(c) //是否为数字
Character.isWhitespace(c) //是否为空白符
Character.isUpperCase(c) // 是否为大写字母
Character.isLowerCase(c) //是否为小写字母
Character.toUpperCase(c) //转换为大写
Character.toLowerCase(c) //转换为小写
Character.toString(c) //转换为字符串
28.字符串的一些方法:
str.charAt(index) //获取某个位置处的字符
str.toCharArray() //转化为字符数组
str.subString(start, end=length) //左闭右开截取字符串,end默认到最后
str.split(char) //按某个字符分割字符串成字符串数组
str.trim() //删除首尾空格
str.indexOf(char or String) / str.lastIndexOf(char or String) //字符串或字符在字符串str中第一次/最后一次出现的位置,没有返回-1
str.replaceAll("old", "new")/replaceFirst("old", "new") //将字符串中的old子串替换成new子串
String类的equal()被重写了,比较的是两个字符串的内容是否相同,与"="效果不一样
str.startsWith(start) / str.endsWith(end) //以...字符串开头或结尾
29.每当出现一个不一样的字符串字面值,就会在堆中用一个空间存放它,被当做一个对象看待。因此,当通过new String(“字面值”)的方式创建字符串,就会创建出两个对象,一个是字面值,一个是String类
31.时间原点对应1970年1月1日8:00(UTC-8),通过new Date()创建的日期是当前日期,而new Date(xxx)创建距离时间原点xxx毫秒的日期。一般得到当前时间戳常用的是System.currentTimeMillis()函数,而非Date.getTime()
32.日历类Calendar能够方便地得到某一天的日期,而不需要复杂的逻辑运算