Java复习

Java复习
SkyforeverJava复习总结
2.1.3 java标识符
规则:
- 标识符只能由数字、字母(包括中文)、下划线_、美元符号$组成,不能含有其它符号。
- 标识符不能以数字开头
- 关键字不能做标识符。
- 例如:public class static void 这些都是关键字,关键字不能做标识符的。
- 标识符严格区分大小写。大写A和小写a不一样。
- 规标识符理论上是没有长度限制的。
2.1.5 Java中的常量
在Java中,final修饰的实例变量一般和static联合使用,称为常量。
例如:
1 | public static final double PI = 3.1415926; |
在C语言中,我们可以使用#define预处理指令来定义常量。
1 |
2.2.3 变量的类型转换
1 小容量可以直接赋值给大容量,称为自动类型转换。
- 容量从小到大的排序为:
- byte < short(char) < int < long < float < double,
- 其中 short和 char 都占用两个字节,但是char 可以表示更大的正整数;
2 大容量不能直接赋值给小容量,需要使用强制类型转换符进行强转。
- 大容量转换成小容量,要想编译通过,必须加强制类型转换符,进行强制类型转换。
1 | 底层是怎么进行强制类型转换的呢? |
需要注意的是:加强制类型转换符之后,虽然编译可以通过,但是运行的时候可能会损失精度。
2.4.3 switch语句
在c语言中,switch里只能判断字符和整型数,Java可以额外判断字符串
2.5.5 跳转语句(break、continue)
break用于跳出本循环语句,执行循环后面的代码
continue用于跳出本次循环,执行下一次循环
2.6 方法
2.6.2 方法的重载
- 什么时候代码会发生方法重载?
- 在同一个类当中,方法名相同,参数列表不同
- 参数列表不同具体指:参数的个数不同,参数的类型不同,参数的顺序不同
- 在同一个类当中,方法名相同,参数列表不同
只要同时满足以上条件,那么我们可以认定方法和方法之间发生了重载机制。
2.7 数组
相关实验:
猜数字游戏
案例2-7 抽取幸运观众
关于C与Java的不同(总结)
1. 无符号数据类型
-
Java:
- Java没有无符号的
byte
、short
、int
和long
数据类型,这一点与C语言有很大的不同。因此,在Java中声明unsigned int m
是错误的。
1
unsigned int m = 10;// Java 不支持无符号整型,这是错误的:
- Java没有无符号的
-
C:
- C语言支持无符号数据类型。
1
unsigned int m = 10;// C 支持无符号整型
2. 数组声明
-
Java:
- 与C语言不同,Java不允许在声明数组时在方括号内指定数组的大小。例如,
int a[12];
在Java中是非法的。
1
2int[] a;// Java 中不能在声明数组时指定大小
a = new int[12]; // 正确的方式 - 与C语言不同,Java不允许在声明数组时在方括号内指定数组的大小。例如,
-
C:
- C语言允许在声明数组时在方括号内指定数组的大小。
1
int a[12];// C 中可以在声明数组时指定大小
3. 数组大小
-
Java:
- 与C语言不同,Java允许使用
int
型变量来指定数组的大小。例如:
1
2int size = 10;
double[] number = new double[size]; - 与C语言不同,Java允许使用
-
C:
- C语言也允许使用
int
型变量来指定数组的大小,但必须在数组声明之前赋值。
1
2int size = 10;
double number[size]; // C99 及以上版本支持变长数组(VLA),在标准C中不支持 - C语言也允许使用
4. 不规则二维数组
-
Java:
- 与C语言不同,Java允许二维数组的列数可不相同,即Java支持不规则的二维数组。
1
2
3
4int[][] irregularArray = new int[3][];//这里没有定义列,这在Java中可行
irregularArray[0] = new int[2];
irregularArray[1] = new int[3];
irregularArray[2] = new int[4]; -
C:
- C语言的二维数组要求所有行的列数相同,不支持不规则的二维数组。
1
int regularArray[3][4]; // C 中的二维数组要求所有行的列数相同
这些示例展示了Java和C语言在无符号数据类型、数组声明和使用方面的主要区别。
面向对象
3.1 面向对象的思想
面向对象编程(OOP)包括三大特征:
1. 封装
- 解释: 封装是将对象的状态(属性)和行为(方法)结合在一起,并隐藏对象的内部实现细节,只暴露必要的接口。这种特性提高了代码的可维护性和安全性。
- 示例:
1
2
3
4
5
6
7
8
9
10
11public class Person {
private String name; // 私有属性,外部不可直接访问
public String getName() { // 公有方法,用于访问私有属性
return name;
}
public void setName(String name) { // 公有方法,用于修改私有属性
this.name = name;
}
}
2. 继承
-
解释: 继承是创建新类时可以基于已有类的定义,继承其属性和方法,从而实现代码重用和扩展。子类可以增加新的属性和方法,也可以重写父类的方法。
-
示例:
1
2
3
4
5
6
7
8
9
10
11public class Animal {
public void eat() {
System.out.println("This animal eats food.");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println("The dog barks.");
}
}
3. 多态
-
解释: 多态是指同一接口可以有不同的实现方式。多态分为编译时多态(方法重载)和运行时多态(方法重写)。多态使得程序在处理不同对象时具有灵活性。
-
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public class Animal {
public void sound() {
System.out.println("动物发出叫声.");
}
}
public class Dog extends Animal {
public void sound() {
System.out.println("狗吠");
}
}
public class Cat extends Animal {
public void sound() {
System.out.println("猫“喵”");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.sound(); // 输出:狗吠
myCat.sound(); // 输出:猫“喵”
}
}
3.2.4 访问控制
Java提供的四种访问控制权限如下:
访问控制修饰符 | 本类 | 同包 | 不同包子类 | 任意位置 |
---|---|---|---|---|
public(公共) | 可以 | 可以 | 可以 | 可以 |
protected(受保护) | 可以 | 可以 | 可以 | 不行 |
default(默认) | 可以 | 可以 | 不行 | 不行 |
private(私有的) | 可以 | 不行 | 不行 | 不行 |
范围从大到小排序:public
> protected
> default
> private
3.3 封装性
封装的代码实现两步:
第一步:属性私有化
第二步:为每个属性提供两个方法:set方法和get方法
- 外部程序只能通过set方法修改属性值,只能通过get方法读取属性值。
- 可以在set方法中设立检查机制来保证数据的安全性。
重要说明:
- set方法和get方法都是实例方法,不能带
static
。 - 不带
static
的方法称为实例方法,调用实例方法必须先创建对象(使用new
关键字)。
3.4 构造方法
什么是构造方法,有什么用?
- 构造方法是一个比较特殊的方法,用于完成对象的创建以及实例变量的初始化。换句话说,构造方法是用来创建对象并且同时给对象的属性赋值。
- 当一个类没有提供任何构造方法时,系统会默认提供一个无参数的构造方法,这个方法不会显示出来,但他存在。
构造方法的调用
-
使用**
new
**运算符来调用构造方法。 -
注意:
- 构造方法名和类名必须一致。
- 构造方法不能(也不需要)指定返回值类型,只能返回0(return 0)作为函数结束标志;
构造方法的重载
- 和普通方法一样,方法输入参数不同即可
3.5 this
关键字
3.5.1. 什么是this
关键字?
this
是一个引用,指向当前对象。- 在类的方法和构造方法中,
this
指向调用该方法的对象。
3.5.2. this
关键字的用途
用于区分实例变量和局部变量
-
当实例变量和局部变量同名时,使用
this
来区分它们。1
2
3
4
5
6
7public class Person {
private String name;
public void setName(String name) {
this.name = name; // this.name指的是实例变量,name指的是参数
}
}
用于调用类的其他构造方法
-
在一个构造方法中调用另一个构造方法,可以避免重复代码。
-
调用时必须是方法中的第一句。
1
2
3
4
5
6
7
8
9
10
11
12
13public class Person {
private String name;
private int age;
public Person() {
this("Unknown", 0); // 调用另一个构造方法,且在方法的第一句
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
返回当前对象
-
方法可以通过返回
this
来实现方法链。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public class Person {
private String name;
public Person setName(String name) {
this.name = name;
return this; // 返回当前对象
}
public void printName() {
System.out.println(this.name);
}
}
// 使用方法
Person person = new Person();
person.setName("John").printName();
3.5.3 注意事项
this
不能在静态方法中使用,因为静态方法属于类,不属于对象。this
只能在实例方法和构造方法中使用。
4.1 类的继承
4.1.1什么是继承?
- 继承是一种面向对象编程的特性,允许子类继承父类的属性和方法。
- 继承使得代码可以重用,子类可以扩展和修改父类的行为。
继承的限制
- Java只支持单继承,即一个类只能继承一个直接父类。
- 但是,一个类可以实现多个接口,这被称为多实现。
继承的优点
- 提高代码的复用性,可维护性。
- 提供了多态的实现基础。
继承的语法:
-
使用
extends
关键字来实现继承。1
2
3
4
5
6
7public class ParentClass {
// 父类的属性和方法
}
public class ChildClass extends ParentClass {
// 子类的属性和方法
}
继承的特点
子类拥有父类的属性和方法
-
子类可以直接使用父类的属性和方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class Animal {
public void eat() {
System.out.println("This animal eats food.");
}
}
public class Dog extends Animal {
public void bark() {
System.out.println("The dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // 调用父类的方法
dog.bark(); // 调用子类的方法
}
}
4.1.2 方法重写(Override)
-
子类可以重写父类的方法,以提供特定的实现。重写的方法必须具有相同的方法签名(方法名、参数列表和返回类型)。
-
使用
@Override
注解来标识重写的方法。1
2
3
4
5
6
7
8
9
10
11
12public class Animal {
public void makeSound() {
System.out.println("Some generic animal sound.");
}
}
public class Dog extends Animal {
public void makeSound() {
System.out.println("The dog barks.");
}
}
4.1.3 使用super
关键字
-
super
关键字用于访问父类的属性和方法,特别是在子类重写了父类的方法时。 -
super
也可以用来调用父类的构造方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class Animal {
public void makeSound() {
System.out.println("一些动物在叫。");
}
}
public class Dog extends Animal {
public void makeSound() {
super.makeSound(); // 调用父类的方法
System.out.println("狗在叫。");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound();
}
}
super
和this
的区别:
特点 | super |
this |
---|---|---|
指向什么 | 指向父类的成员或构造方法 | 指向当前对象的成员或构造方法,没有就找父类 |
使用范围 | 在子类中使用 | 在类的任何地方使用 |
调用构造 | 调用父类的构造方法,必须放在子类构造方法首行 | 调用本类的构造方法,必须放在构造方法首行 |
总结:super
主要用于访问父类的成员和调用父类的构造方法,而this
用于访问当前对象的成员和调用自身的构造方法。
4.2 final关键字
类用final关键字修饰后,该类不可被继承(不能有子类)
4.3 抽象类和接口
注意事项
- 抽象类和接口都是用于实现类的多态性,提供了规范和约束。
- 抽象类适用于具有共同特征的类之间的继承关系,而接口适用于不同类之间的共性行为和规范定义。
在Java中,抽象类和接口都是用来实现抽象化的工具,但它们有不同的用途和特点。
下面通过一个例子来展示它们的区别。
抽象类
抽象类可以包含抽象方法(没有方法体的方法)和具体方法(有方法体的方法)。抽象类不能被实例化,只能被继承。
1 | abstract class Animal { |
接口
接口只能包含抽象方法~~(Java 8及以后的版本中可以包含默认方法和静态方法)~~。接口中的方法默认是 public
和 abstract
,可以被多个类实现。
1 | interface Animal { |
区别总结
- 抽象类可以有构造方法、成员变量和具体方法,而接口不能有实例变量~~(Java 8及以后可以有静态变量)~~。
- 一个类只能继承一个抽象类,但可以实现多个接口。
- 抽象类适用于共享代码的情况,而接口适用于定义一组方法,让不同类实现。
案例4-5 图形的面积与周长计算程序
4.4 多态
什么是多态:
- 多态指的是同一个方法在不同对象上具有不同的表现形式,可以实现不同对象的同名方法的多种不同行为。
- 例如子类重载或重写父类的方法
向上转型和向下转型的概念:
-
向上转型(upcasting):子类对象可以自动转换为父类类型。
- 示例:
Animal a = new Cat();
- 示例:
-
向下转型(downcasting):父类对象需要强制转换为子类类型。
-
示例:
Cat c = (Cat)a;
,需要添加强制类型转换符。 -
向下转型容易出现
ClassCastException
(类型转换异常)。 -
如何避免这个风险?
-
可以使用
instanceof
运算符,在程序运行阶段动态判断某个引用指向的对象是否为某一种类型。- 示例:
1
2
3
4
5Animal a = new Cat();
if (a instanceof Cat) {
Cat c = (Cat) a;
// 调用 Cat 类的特有方法
}
-
-
4.7 异常
4.7.1 什么是异常
异常是指程序在运行过程中遇到的不正常情况,可能导致程序无法继续执行的问题。
Java中的异常是以对象的形式存在的,它们都是 Throwable
类或其子类的实例。
4.7.2 try…catch和finally
-
try…catch块:用于捕获可能引发异常的代码块,捕获到异常后进行相应的处理。
1
2
3
4
5
6
7
8
9try {
// 可能引发异常的代码
} catch (ExceptionType1 e1) {
// 处理异常类型1的代码
} catch (ExceptionType2 e2) {
// 处理异常类型2的代码
} finally {
// 无论是否发生异常,都会执行的代码块
} -
finally块:用于在不管是否发生异常的情况下都执行的代码块,通常用于释放资源等操作。
4.7.3 throws关键字
throws
关键字用于在方法声明中标识该方法可能会抛出的异常,表示该方法不处理异常,而是将异常抛给调用者处理。
1 | public void doSomething() throws SomeException { |
Java API
5.1 字符串类
字符串类在Java中非常重要,用于表示和操作字符串数据。常用的字符串类是String
类,它提供了丰富的方法用于字符串的操作,例如拼接、截取、替换等。
1 | String str = "Hello, World!"; |
案例5-3 模拟用户注册
5.3 Math和Random类
Math类
Math
类包含了各种数学运算的静态方法,例如取整、取绝对值、计算平方根、求最大最小值等。
1 | int num1 = 10; |
Random类
Random
类用于生成随机数,可以生成不同范围的整数或浮点数随机数。
1 | Random random = new Random(); |
5.4 日期和时间类
日期和时间类用于表示和操作日期、时间和时间戳。Java中常用的日期和时间类有Date
类、Calendar
类和SimpleDateFormat
类。
1 | Date date = new Date(); // 创建当前日期时间对象 |
集合
6.1 集合简述
Java集合框架提供了一组用于存储和操作数据的类和接口。集合可以动态地存储、检索和操作对象。集合框架主要包含以下接口:List
、Set
、Queue
和Map
,每个接口有不同的实现类。
6.3 List集合
List
接口表示一个有序的集合,允许存储重复的元素。常用的List
实现类有ArrayList
、LinkedList
和Vector
。
6.3.2 ArrayList集合
ArrayList
是List
接口的实现类,使用动态数组来存储元素。它提供了快速的随机访问时间,但在插入和删除元素时性能较低。
1 | ArrayList<String> arrayList = new ArrayList<>(); |
6.3.4 Iterator接口
Iterator
接口用于遍历集合中的元素。它提供了hasNext()
、next()
和remove()
方法。
1 | List<String> list = new ArrayList<>(); |
6.4 Set接口
Set
接口表示一个不包含重复元素的集合。常用的Set
实现类有HashSet
、LinkedHashSet
和TreeSet
。
1 | Set<String> set = new HashSet<>(); |
Java集合框架提供了丰富的数据结构和操作方法,使得数据的存储和处理变得更加灵活和高效。
I/O流式传输
7.2 字节流
字节流是以字节为单位进行数据读写的流,常用于处理二进制数据或者文本文件。Java中的字节流主要包括InputStream和OutputStream两个抽象类,以及它们的具体实现类如FileInputStream、FileOutputStream等。
字节流的使用示例:
1 | import java.io.*; |
7.3 字符流
字符流是以字符为单位进行数据读写的流,常用于处理文本文件。Java中的字符流主要包括Reader和Writer两个抽象类,以及它们的具体实现类如FileReader、FileWriter等。
字符流的使用示例:
1 | import java.io.*; |
字节流适用于处理二进制数据或者文本文件,而字符流适用于处理文本文件,可以更方便地处理字符编码和字符集。
多线程
8.2 线程的创建
在Java中,线程的创建有两种方式:继承Thread类和实现Runnable接口。
8.2.1 继承Thread类
继承Thread类是创建线程的一种方式,需要重写Thread类的run()方法来定义线程的执行逻辑。
示例:
1 | class MyThread1 extends Thread { |
8.2.2 实现Runnable接口创建多线程
另一种创建线程的方式是实现Runnable接口,然后将实现了Runnable接口的类传递给Thread类的构造方法。
示例:
1 | class MyThread2 implements Runnable { |
通过实现Runnable接口,可以更灵活地管理线程的生命周期和资源,并且可以避免Java单继承的限制。在实际开发中,通常推荐使用实现Runnable接口的方式来创建多线程,因为它更符合面向对象的设计原则。
继承Thread类 | Runnable接口
两者实现多线程的区别
第一个继承Thread类来实现多线程,其实是相当于拿出三件事即三个卖早餐10份的任务分别分给三个窗口,他们各做各的事各卖各的早餐各完成各的任务,因为MyThread继承Thread类,所以在newMyThread的时候在创建三个对象的同时创建了三个线程;
而实现Runnable, 相当于是拿出一个卖早餐10份的任务给三个人去共同完成,newMyThread相当于创建一个任务,然后实例化三个Thread,创建三个线程即安排三个窗口去执行。
**一个类只能继承一个父类,存在局限;一个类可以实现多个接口。**在实现Runnable接口的时候调用Thread的Thread(Runnable run)或者Thread(Runnablerun,String name)构造方法创建进程时,使用同一个Runnable实例,建立的多线程的实例变量也是共享的;但是通过继承Thread类是不能用一个实例建立多个线程,故而实现Runnable接口适合于资源共享;当然,继承Thread类也能够共享变量,能共享Thread类的static变量;
其实,抽象来说,这并不是Thread类和Runnable接口的区别了,这可以看做是接口和继承的问题。我们弄懂了接口和继承,就不难理解Thread和Runnable。
在刚接触的时候可能会有些迷糊这二者的区别于联系,但是实践和总结过后我们会发现这是两个完全不同的实现多线程,一个是多个线程分别完成自己的任务,一个是多个线程共同完成一个任务。其实,在实现一个任务用多个线程来做也可以用继承Thread类来实现,只是比较麻烦,一般我们用实现Runnable接口来实现。
连接数据库
10.3 实现JDBC程序
1 | import java.sql.*; |