1.关键字
1.1关键字特点
- 关键字的字母全部小写
- 常用的代码编辑器,针对关键字有特殊颜色标记
2.常量
2.1 常量概述
常量:在程序运行过程中,其值不可以发生改变的量。
2.2 常量分类
常量类型 | 说明 | 举例 |
---|---|---|
字符串常量 | 用双引号括起来的内容 | “Hello”,“厚厚” |
整数常量 | 不带小数的数字 | 73,-73 |
小数常量 | 带小数的数字 | 7.3,-7.3 |
字符常量 | 用单引号括起来的内容 | ‘A’,‘73’,‘七十三’ |
布尔常量 | 布尔值、表示真假 | true, false |
空常量 | 特殊值、空值 | null |
3.数据类型
3.1 数据类型
Java是强类型语言
Java有8种基本类型,byte、int、long、char、float、double、boolean各占1 4 8 2 4 8 1个字符。其中
byte:8位 一个字节
int:32位 四个字节
long: 64位 八个字节
char:: 16位 两个字节
float: 32位 四个字节
double: 64位 八个字节
boolean: 8位 一个字节
4. 变量
4.1 变量概述
变量:在程序运行过程中,其值可以发生改变的量
4.2 变量的定义
- 格式:数据类型 变量名 = 变量值;
- 范例 int a = 10;
5. 标识符
5.1 标识符规则
- 由数字、字母、下划线、和$组成
- 不能以数字开头
- 不能是关键字
- 区分大小写
5.2 命名约定
小驼峰命名法: 主要针对方法和变量
- 标识符是一个单词的时候,首字母小写。name
- 标识符由多个单词组成的时候,第一个单词首字母小写,其他单词的首字母大写。firstName
- 代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束。
大驼峰命名法: 主要针对类
- 标识符是一个单词的时候,首字母大写。Student
- 标识符由多个单词构成时每个单词的首字母大写。StudentName
6.类型转换
6.1 自动类型转换
把一个表示数据范围小的数值或者变量赋值给另一个表示数据范围大的变量
6.2 强制类型转换
把一个表示数据范围大的数值或者变量赋值给一个表示范围小的变量
- int a = (int) 7.3;
7. 运算符
7.1 自增、自减运算符
- 运算符:++ –
- 表达式:x++ x–
- int j = i++;先赋值后自增,int j = ++i; 先自增后赋值
7.2 关系运算符
符号 | 说明 |
---|---|
== | a==b,判断a,b是否相等,成立为true,不成立为false |
!= | a!=b,判断a是否不等b,成立为true,不成立为false |
> | a>b,判断a是否大于b,成立为true,不成立为false |
>= | a>=b,判断a是否大等于b,成立为true,不成立为false |
< | a<b,判断a是否小于b,成立为true,不成立为false |
<= | a<=b,判断a是否小等于b,成立为true,不成立为false |
7.3 逻辑运算符
符号 | 作用 | 说明 |
---|---|---|
& | 与 | 有false则false,无论左边真假右边都要执行 |
| | 或 | 有true则true,无论左边真假右边都要执行 |
^ | 且 | 相同为true,不同为false |
! | 非 | 结果与a相反 |
&& | 短路与 | 左边为false,右边不执行。左边为true,右边执行 |
|| | 短路或 | 左边为false,右边执行。左边为true,右边不执行 |
7.4 三元运算符
- 格式:关系表达式?表达式1:表达式2
- 范例:x>y?x:y;
- 先计算x>y,若为true则返回表达式1:x
- 若为false则返回表达式2:y
8. 三种循环的区别
三种循环的区别
- for和while先判断条件是否成立,然后决定是否执行(先判断后执行)
- do…while先执行一次,后判断条件是否成立(先执行后判断)
9. 内存分配
9.1 Java中内存分配
- 栈内存:存储局部变量
定义在方法中的变量,例如:arr
使用完毕,立即消失
- 堆内存:存储new的内容(实体,对象)
数组在初始化时,会为存储空间添加默认值
整数:0
浮点数:0.0
布尔:false
字符:空字符
引用数据类型:null
每一个new出的东西都有一个地址值,使用完毕会在垃圾回收器空闲时被回收
10.方法
10.1 方法的概述
- 方法是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集
- 方法必须先创建才可以使用,改过程称为方法的定义
- 方法需要被调用才能执行
10.2 形参和实参
- 形参:方法定义中的参数 public static void max(int x,int y) (int x,int y)为形参
- 实参:方法调用中的参数 max(10,20)为实参
- 对于基本数据类型的参数,形参的改变不影响实参的值
- 对于引用类型的参数,形参的改变会影响实参的值
10.3 方法注意事项
- 方法不能嵌套定义
- void无返回值,但也可单独写个return;
10.4 方法重载和重写
重载
- 发生在同一个类中,与返回值无关。
- 在调用的时候Java虚拟机会通过参数的不同来区分同名的方法。
- 方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
重写
- 重写是子类对父类的允许访问的方法的实现过程进行重新编写,发生在子类中。
- **方法名、参数列表必须相同,**返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
- 如果父类方法访问修饰符为 private 则子类就不能重写该方法。
11. 类和对象
类:类是对现实生活中一类具有共同属性和行为的事物的抽象
对象:是能够看到的真实存在的尸体
- 类是对象的抽象
- 对象是类的实体
11.1 类的组成
类的组成:属性和行为
- 属性:在类中通过成员变量来体现(类中方法外的变量)
- 行为:在类中通过成员方法来体现
11.2 多个对象指向相同
当两个对象的指向相同也就是地址值相同时,其中一个对象修改堆内存内容,另一个对象访问时也是改变过的。
Student s1 = new Student();
s1.age=18;
//把第一个对象的地址值赋值给第二个对象
Student s2 = s1;
s2.age = 20;
sout(s1.age) //s1.age=20
sout(s2.age) //s2.age=20
12. 成员变量和局部变量
区别 | 成员变量 | 局部变量 |
---|---|---|
类中的位置不同 | 类中方法外 | 方法内或者方法声明上 |
内存中的位置不同 | 堆内存 | 栈内存 |
生命周期不同 | 随着对象的存在而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的调用完毕而消失 |
初始化值不同 | 有默认初始值,因此定义时可以不用赋初值 | 没有默认初始值,因此定义时必须赋初值 |
13. 封装
13.1 private 关键字
- 是一个权限修饰符
- 可以修饰成员变量和成员方法
- 作用是保护成员不被其他类使用
- 被private修饰的成员只能在本类中才能访问
- 如果要使用被private修饰的成员变量,需要用get()和set()方法
13.2 this关键字
- this修饰的变量用于指代成员变量
- this用于解决局部变量和成员变量同名时局部变量隐藏成员变量
- this代表所在的对象引用。方法被哪个对象调用,this就代表哪个对象
13.3 封装的好处
- 通过方法来控制成员变量的操作,提高了代码的安全性
- 把代码用方法进行封装,提高了代码的复用性
14. 构造方法
构造方法注意事项
- 构造方法的创建
- 如果没有定义构造方法,系统会给出一个默认的无参构造方法
- 反之若定义了构造方法,系统则不提供默认的无参构造方法
- 构造方法的重载
- 如果自定义了带参构造方法,还要使用无参构造方法,就必须再写一个无参构造方法
- 无论是否使用,均建议手动写一个无参构造方法
15. 字符串
15.1 String
字符串的特点
- String不可变,它们的值在创建后不能被更改
- 虽然不可变,但是可以共享
- String底层原理是字节数组(byte[])
- JDK9及以后效果上相当于字节数组(byte[]),JDK8及以前相当于字符数组(char[])
String的构造方法
方法名 | 说明 |
---|---|
public String() | 创建一个空白字符串对象,不含有任何内容 |
public String(char[] chs) | 根据字符数组的内容创建字符串对象 |
public String(byte[] bys) | 根据字节数组的内容创建字符串对象 |
String s=“ab” | 直接赋值的方式创建字符串对象,内容就是=右边的内容 |
String对象的特点
-
通过new创建的字符串对象,每一次new都会申请一个内存空间,虽然内容相同,但是地址值不同
char[] chs = {'a','b'}; String s1 = new String(chs); String s2 = new String(chs); //s1==s2; false //s1.euqals(s2); true
-
通过 “” 方式给出的字符串,只要字符串序列相同(顺序和大小写),无论在程序中出现几次,JVM都只会创建一个String对象,并在字符串池中维护
String s1 = "ab";
String s2 = "ab";
//s1==s2; true
//s1.euqals(s2); true
15.2 ==和equals
== : 它的作用是判断两个对象的地址是不是相等。即判断两个对象是不是同一个对象
- 基本数据类型==比较的是值
- 引用数据类型==比较的是内存地址
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
-
情况 1:类没有覆盖 equals()方法
- 则通过 equals()比较该类的两个对象时,等价于通过“==”比较这两个对象
-
情况 2:类覆盖了 equals()方法
- 覆盖 equals()方法来两个对象的内容相等;若它们的内容相等,则返回 true(即,认为这两个对象相等)
例子:
public class test1 {
public static void main(String[] args) {
String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
// aa == bb true
// a == b false,非同一对象
// a.equals(b) true
//42 == 42.0 true
}
}
说明:
- String 中的 equals 方法是被重写过的,因为 object 的 equals 方法是比较的对象的内存地址,而 String 的 equals 方法比较的是对象的值。
- 当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
15.3 字符串操作
遍历字符串
String s = "abc";
for (int i = 0; i < s.length(); i++) { //s.length()获取字符串长度
System.out.println(s.charAt(i)); //s.charAt(i) 返回指定索引处的值
}
统计字符出现次数
public class StringDemo02 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int countNum = 0;
int countB = 0;
int countS = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c >= 'A' && c <= 'Z') {
countB++;
} else if (c >= 'a' && c <= 'z') {
countS++;
} else if (c >= '0' && c <= '9') {
countNum++;
}
}
System.out.println(countNum);
System.out.println(countB);
System.out.println(countS);
}
拼接字符串(String版)
public class StringDemo03 {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
String s = change(arr);
System.out.println(s);
}
public static String change(int[] arr) {
String s = "";
s += "[";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
s += arr[i];
} else {
s += arr[i];
s += ",";
}
}
s += "]";
return s;
}
}
字符串反转(String版)
public class StringDemo04 {
public static void main(String[] args) {
String s = "abcd";
String reverse = reverse(s);
System.out.println(reverse);
}
public static String reverse(String s) {
String s1 = "";
for (int i = s.length() - 1; i >= 0; i--) {
s1 += s.charAt(i);
}
return s1;
}
}
15.4 StringBuilder
StringBuilder常用方法
方法名 | 说明 |
---|---|
StringBuilder append | 添加数据并返回对象本身 |
StringBuilder reverse | 返回逆序字符串 |
StringBuilder和String相互转换
-
StringBuilder转String
- toString()
StringBuilder sb = new StringBuilder(); sb.append("a"); String s=sb.toString(); ystem.out.println(s);
-
String转StringBuilder
String s="ab"; StringBuilder sb= new StringBuilder(s); System.out.println(sb);
拼接字符串(StringBuilder版)
public class StringBuilderDemo {
public static void main(String[] args) {
int[] arr = new int[]{1, 2, 3};
String s = arrayToString(arr);
System.out.println(s);
}
public static String arrayToString(int[] arr) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
sb.append(arr[i]);
} else
sb.append(arr[i]).append(",");
}
sb.append("]");
return sb.toString();
}
}
字符串反转(StringBuilder版)
public class StringBuilderDemo02 {
public static void main(String[] args) {
String s = "abc";
String reverse = reverse(s);
System.out.println(reverse);
}
public static String reverse(String s) {
StringBuilder sb = new StringBuilder(s);
String s1 = sb.reverse().toString();
return s1;
//return new StringBuilder(s).reverse().toString(s);
}
}
16. ArrayList
16.1 创建与添加
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> as = new ArrayList<String>();
as.add("a"); //添加元素
as.add("b");//添加元素
as.add(1, "c"); // 在指定位置(index)添加元素
System.out.println(as);
}
}
16.2 常用方法
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> as = new ArrayList<String>();
as.add("a");
as.add("b");
as.add(1, "c");
as.remove("c"); //删除指定元素
as.remove(1);//删除指定索引处的元素
as.set(1, "d");//修改指定索引处的元素
System.out.println(as.get(1));//返回指定索引处的元素
System.out.println(as.size());//返回集合长度
System.out.println(as);
}
}
16.3 集合存储与遍历
普通for
public class Demo02 {
public static void main(String[] args) {
ArrayList<String> as = new ArrayList<String>();
as.add("a");
as.add("b");
as.add("c");
//普通for
for (int i = 0; i < as.size(); i++) {
String s = as.get(i);
System.out.print(s);
}
}
}
增强for
public class Demo02 {
public static void main(String[] args) {
ArrayList<String> as = new ArrayList<String>();
as.add("a");
as.add("b");
as.add("c");
//增强for
for (String s : as) {
System.out.print(s);
}
}
}
17. 继承
继承可以使得子类具有父类的属性和方法,还可以在子类中重新定义追加属性的方法
17.1 继承的特点
- Java类只支持单继承,不支持多继承。但是可以多层继承
- 子类拥有父类对象所有的属性和方法(包括私有属性和方法),但是子类无法访问父类中的私有属性和方法,只是拥有
- 子类可以有自己的属性和方法,即子类可以对父类进行拓展
- 子类可以用自己的方式实现父类的方法
- 子类方法访问变量优先级:子类局部变量(直接用变量名) > 子类成员变量(this.变量名) > 父类成员变量(super.变量名)
17.2 继承的好处和弊端
好处
- 提高了代码的复用性(多个类相同的成员可以放到同一个类中)
- 提高了代码的维护性(如果方法代码需要修改,修改一处即可)
弊端
- 继承让类与类直接产生关系,增强了类的耦合性。因此当父类发生改变时,子类不得不发生改变,削弱了子类的独立性
什么时候使用继承
- is a
- 假设有两个类A和B。若A是B的一种或B是A的一种,则可以考虑使用继承
- 譬如:A类是苹果,B类是水果。苹果是水果的一种,因此可以考虑A extends B
17.3 继承中构造方法访问特点
- 子类中所有的构造方法默认都会访问父类的无参构造方法。原因是:子类初始化前,需要先完成父类数据的初始化
- 每一个子类构造方法的第一条语句默认是:super();
- 如果父类中没有无参构造方法,则需要通过super去调用父类带参构造方法,完成父类数据初始化
18. 修饰符
18.1 权限修饰符
修饰符 | 同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | 能被访问 | 不能 | 不能 | 不能 |
默认 | 能被访问 | 能被访问 | 不能 | 不能 |
protected | 能被访问 | 能被访问 | 能被访问 | 不能 |
public | 能被访问 | 能被访问 | 能被访问 | 能被访问 |
18.2 状态修饰符
final
- final可以修饰成员方法、成员变量、类
- final修饰的方法不能被重写
- final修饰的变量为常量,不能修改(再次赋值)
- final修饰的类为最终类,不能被继承
- final修饰基本类型,则基本类型的数据值不能改变
- final修饰引用类型,则引用类型的地址值不能改变,但内容可以改变
static
- 被所有对象共享的成员,用static静态修饰
- 可以通过类名调用Stednt.school=“xxx”; 也可以通过对象名调用
- 非静态成员方法可以访问静态成员方法和静态成员变量,也能访问非静态的成员方法和非静态的成员变量
- 静态的成员方法只能访问静态的成员方法和成员变量
19. 多态
19.1 多态概述
多态的前提和体现
- 有继承/实现关系
- 有方法重写
- 有父类引用指向之类对象
多态的实现方式
- 继承。多个子类对同一方法的重写
- 接口。实现接口并覆盖接口中同一方法
19.2 多态中成员访问特点
- 成员变量:编译看左边,执行看左边
- 成员方法:编译看左边,执行看右边
19.3 多态的好处和弊端
好处
- 提高了程序的拓展性
- 体现:定义方法时,使用父类作为参数,将来在使用的时候,使用具体的子类型参与操作
弊端
- 不能使用子类的特有功能(方法)
19.4 多态的转型
-
向上转型
- 从子到父
- 父类引用指向之类对象 (Animal a = new Cat(); )
-
向下转型
- 从父到子
- 父类引用转为子类对象(Cat c = (Cat)a; )
20. 抽象类
20.1 抽象类特点
- 没有方法体的方法应该定义为抽象方法
- 抽象类中不一定有抽象方法,有抽象方法的一定是抽象类
- 抽象类不能实例化。需要参照多态的方式,通过子类对象实例化
- 抽象类的子类要么重写抽象类中所有的抽象方法,要么本身是抽象类
20.2 抽象类的成员特点
- 抽象类中可以有成员变量。其中成员变量可以是变量,也可以是常量
- 抽象类中可以有构造方法,但是不能实例化。构造方法的作用是:用于子类访问父类数据的初始化
- 抽象类中可以有抽象方法(用于限定子类必须完成某些操作),也可以有非抽象方法(提高代码复用性)
21. 接口
21.1 接口的特点
- 接口不能实例化。需要参照多态的方式,通过实现类对象实例化
- 接口的实现类要么重写接口中的所有抽象方法,要么是抽象类
21.2 接口的成员特点
- 接口中的成员变量是常量。默认修饰符为:public static final
- 接口中没有构造方法和成员方法,只能是抽象方法。默认修饰符为:public abstract
- Java8 后接口可以有默认实现( default )
- Java8 后接口可以有静态方法( static)
- Java9 后接口可以有私有方法( private )
22.类和接口的关系以及接口和抽象类的区别
22.1 类和接口的关系
类和类的关系
- 继承关系。只能单继承,不能多继承,但是可以多层继承
类和接口的关系
- 类实现接口。一个类可以实现单个接口,也可以实现多个接口。还可以在继承一个类的同时实现多个接口
接口和接口的关系
- 接口继承接口。可以单继承,也可以多继承
22.2 接口和抽象类的区别
- 接口的方法默认是 public,所有方法在接口中不能有实现,抽象类可以有非抽象的方法
- 接口中的实例变量默认是 final 类型的,而抽象类中则不一定
- 一个类可以实现多个接口,但最多只能实现一个抽象类
- 一个类实现接口的话必须实现接口的所有方法,而抽象类不一定
- 接口不能用 new 实例化,但可以声明,但是必须引用一个实现该接口的对象 从设计层面来说,抽象是对类的抽象,是一种模板设计,接口是行为的抽象,是一种行为的规范。
23. 内部类
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
- 在方法内定义的叫做局部内部类,在方法外定义的叫成员内部类
23.1 成员内部类
成员内部类对象创建
-
格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象
-
Outer.Inner oi = new Outer().new Inner();
-
或者在外部类中定义一个方法,创建内部类对象并调用内部类方法
-
public class Outer { private int num = 10; private class Inner { public void show() { System.out.println("成员内部类被调用"); } } //定义成员方法调用成员内部类 public void method() { Inner i = new Inner(); i.show(); } } public class OuterDemo { public static void main(String[] args) { Outer o = new Outer(); o.method(); } }
23.2 局部内部类
public class Outer2 {
private int num = 10;
//定义成员方法
public void method() {
//定义局部内部类
class Inner {
//定义show方法
public void show() {
System.out.println("局部内部类show方法被调用" + num);
}
}
//创建局部内部类对象
Inner i = new Inner();
//通过局部内部类对象调用show方法
i.show();
}
}
public class OuterDemo {
public static void main(String[] args) {
//创建外部类对象
Outer2 o2 = new Outer2();
//调用外部类类成员方法
o2.method();
}
}
23.3 匿名内部类
- 前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
- 本质:是一个继承了该类或者实现类该接口的子类匿名对象
new Inter(){
@Override
public void show(){...}
}
24. 基本类和包装类
对照表
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
24.1 int 和 String 相互转换
int 转 String
public class Demo {
public static void main(String[] args) {
int num = 10;
String s = String.valueOf(num);
System.out.println(s);
}
}
String 转 int
public class Demo {
public static void main(String[] args) {
String s = "10";
int i = Integer.parseInt(s);
System.out.println(i);
}
}
24.2 字符串数据排序
public class Demo {
public static void main(String[] args) {
String s = "91 27 46 38 50";
//分割元素得到String数组
String[] split = s.split(" ");
//定义int数组用于接收
int[] arr = new int[split.length];
//把String数组转换为int数组
for (int i = 0; i < split.length; i++) {
arr[i] = Integer.parseInt(split[i]);
}
//排序
Arrays.sort(arr);
//定义StringBuilder用于后续拼接
StringBuilder sb = new StringBuilder();
//进行字符串拼接
for (int j = 0; j < arr.length; j++) {
if (j == arr.length-1) {
sb.append(arr[j]);
} else sb.append(arr[j]).append(" ");
}
//输出拼接后的字符串
String result = sb.toString();
System.out.println(result);
}
}
24.3 自动装箱和拆箱
- 装箱:把基本数据类型转换为对应的包装类类型
- 拆箱:把包装类类型转换为对应的基本数据类型
Integer i = 100=Integer.valueOf(100); //自动装箱
i+ = 200=i.intvalue()+200;
//i=i+200;i+200 自动拆箱;i=i+200自动装箱
25. 异常
异常体系
- Error:严重问题,不需要处理
- Exception:程序本身可以处理的异常,可以通过
catch
来进行捕获。Exception
又可以分为 受检查异常(必须处理) 和 不受检查异常(可以不处理)。 - RuntimeException:俗称运行时异常。在编译期是检查,运行时报错
- 非RuntimeException:俗称编译时异常。编译期就必须处理,否则程序不能通过编译
25.1 异常处理
try…catch
public class Demo01 {
public static void main(String[] args) {
System.out.println("Start");
method();
System.out.println("End");
}
public static void method() {
try {
int[] arr = new int[]{1, 2};
System.out.println(arr[2]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("索引越界");
e.printStackTrace(); //输出异常信息到控制台
} finally {
System.out.println("啊哈哈哈");
}
}
}
- 执行流程
- 从try里面的代码开始执行。出现异常,自动生成一个异常类对象,该异常对象被提交给Java运行时的系统。当Java运行时系统接收到异常对象时,到catch中去找匹配的异常类,找到后进行异常处理。finally无论如何都会执行到
Throwable 类常用方法
public string getMessage()
:返回异常发生时的简要描述public string toString()
:返回异常发生时的详细信息public string getLocalizedMessage()
:返回异常对象的本地化信息。使用Throwable
的子类覆盖这个方法,可以生成本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()
返回的结果相同public void printStackTrace()
:在控制台上打印Throwable
对象封装的异常信息