填空题
课程推荐的 jdk 下载网址为 jdk.java.net
使用命令行编译程序:javac -d bin stc*.java
使用命令行运行程序: java -cp bin 类名
java 语言标识符:字母、数字、下划线和美元符号,数字不能做首字母
java 语言中标识符区分大小写
java 语言中基本类型:byte boolean char short int long float double
java 语言中数据类型分为基本数据类型 和引用类型
Java语言中基本数据类中的数值类型都是有符号的
java 语言声明常量时应使用的关键字是 final
String str = " "+ 23 //在23前面添加语句把23转换成String类型
int x = Integer.valueOf ("23"); int y = x + 1; //添加语句将字符串"23"转换为整型
int[] x 中变量 x 属于引用类型数据
封装
绝大多数情况下,interface 只有借助具体的 class 实现它的功能。
java 语言中核心的概念是 class ,不能在 class 的"{"和"}"之外定义变量和函数。
顶层语法元素是指在源文件中可以直接定义的程序语言语法元素。
其他的如变量、方法只能定义在顶层语法元素之内。
class 把一组相关的数据和操作封装在其中,而 package 将一组相关的 class (和 interface、enum、record)封装在其中。
class中的内容
-
成员
- 成员变量:表示对象的属性
- 成员方法:表示对象的行为
- (其他的内部顶层语法元素)
-
非成员
- 构造方法
实例成员和类成员
实例成员必须创建所属类的对象,只能通过对象的变量利用 "."操作符加上成员名称来访问。
成员定义时添加 static 关键字,称为类成员。
类成员不需要创建对象,可以直接通过可以直接通过类名称"."操作符加类成员来访问。
类方法只能访问类成员,不能在方法的代码中使用实例成员。
可以在 class 中定义其他的 class。(称为内部类或者接口)
非成员(构造方法)
构造方法不属于类的成员。
构造方法没有返回值,名称与类名相同。
构造方法在使用 new 关键字创建对象时使用,返回对象的引用。
如果构造方法被重载,则根据传递的实参的类型和数量确定实际执行时调用的构造方法。
构造方法重载是指在同一个类中定义了多个构造方法,它们的方法名相同但参数列表不同
只有在源代码中没有定义构造方法的情况下,编译器才会创建一个无参数的构造方法,这个无参构造方法称为默认构造方法(无参构造方法不一定是默认构造方法)
构造方法也和成员方法一样,可以被重载。
可以在定义构造方法时,使用 this 关键字调用其他重载的构造方法,必须是方法体中第一句。
this关键字表示对象自身,通常用在方法形参与成员变量同名时,也可以在其他为了区分二者的情况下使用。
this 关键字不能用于 static 方法内
包
包将一组相关的 class 、interface组织在一起,主要起到区分命名空间的作用,不同的包中可以各自定义自己类,即使相同的类名称,也不会造成命名冲突。
包名由一个或多个子包名用"."连接起来组成,每个子包名必须符合 Java 语言的标识符命名规则。
标识符由字母、数字、下划线(_)和美元符号($)组成。,第一个字符不能是数字。
包名一般使用小写字母,且采用逆域名命名规则。
如果要将源文件中的所有类都添加到某个包中,必须在源文件中添加 package语句,例如 package pack.age.name
包声明语句必须是源文件中第一行非注释语句。
没有包声明语句的源文件,其中的类属于默认包。
如果要使用包中的若干类,则必须在源文件中添加 import 语句:
- 导入包中的所有类:
import pack.age.name.*;
- 导入包中的某个类:
import pack.age.name.ClassName;
- 导入包中某个类的类成员:
import static Math.PI;
主类
一个类成为主类必须同时具备两个条件:
- 具有
public static void main(String[] args)
方法 - 在使用 java 命令执行时作为命令行参数指定该类。
一个类如果位于某个包中,则它的完整类名 = 包名+类名,如:xsyu.java2023.demo.Hello
运行时必须指定主类的完整名称
一个 class 定义必备的三个条件是:class 关键字、类名、{}
Java 源文件的名称必须和其中的 public 类的名称相同。
对于一个属于非默认包的类,它编译后的 class 文件必须保存在和包名对应的目录结构下。
开发过程的改变
假设 Hello.java 保存在 当前目录的 src 子目录下,编译命令为:javac -d bin src\*.java
这条命令把位于当前目录的 src 子目录中所有 java 源文件都编译成 .class 文件,保存在当前目录的 bin 目录下,可以看到 bin 目录下自动根据包名建立好了嵌套好的文件夹结构,Hello.class 保存在最底层的 demo 目录下。
要运行上面编译好的 Hello.class 程序,运行命令为java -cp bin xsyu.java2023.demo.Hello
interface
interface 中通常只定义两类内容:
- 常量,但 public static final通常省略
- 抽象方法,但 public abstract 通常省略
实现接口
java
class ClassName implements[interface列表]{
//······
}
一个 class 可以实现多个 interface
所谓实现(implements)就是把 interface 中定义的抽象方法具体化,定义出这些方法的具体代码
如果一个类只实现了部分 interface 中定义的抽象方法具体化,则该类必须被定义为 abstrac class .未实现的方法无需在 abstrac class 中再声明。
一个非抽象类必须实现 implemnts 列表中的所有接口的所有方法。
可以声明 interface 类型的变量,把实现了同一 interface 的 class 对象赋值给对应 interface 类型的变量。但不可以用 new 关键字创建 interface 类型的变量,因为其中有未明确定义的抽象方法。
java
interface MyInterface {
void myMethod();
}
class MyClass implements MyInterface {
public void myMethod() {
System.out.println("Implementation of myMethod");
}
}
public class Main {
public static void main(String[] args) {
// 声明接口类型的变量
MyInterface myObject;
// 将实现了相同接口的类对象赋值给变量
myObject = new MyClass();
// 调用接口方法
myObject.myMethod(); // 输出:Implementation of myMethod
}
}
abstract class
抽象方法:abstract Type method([参数列表]); 添加了 abstract 关键字装饰,但没有定义方法体的方法。
抽象类中可以包含 abstract 方法 ,也可以不包含 abstract 方法。
如果一个 class 中定义了 abstract 方法,则这个 class 必须被定义为 abstract class
抽象类中可以定义构造方法
和 interface 一样,可以声明某个 abstract class 类型的变量,把某个继承了这个 abstract class 的具体类对象赋值给对应 abstract class 类型的变量。但不可以使用 new 关键字创建 abstract class 类型的变量
访问控制关键字
public: 所有代码都可以访问
protected: 除同一个 package 中的其他类可以访问外,即使属于不同包的子类也可以访问。
默认(无修饰符): 默认只有同一个 package 中的其他类可以访问
private: 只有类自身的成员方法和构造方法可以访问
通常情况下,成员变量都定义为 private ,然后根据需要定义读取或者修改成员变量的方法。
成员方法也只在明确需要外界访问时,定义成 public 等相对宽松的访问范围
继承
java
class ClassName extends SuperClass{
//
}
interface InterfaceName extends /*[interface列表]*/{
//
}
在 java 语言中,class 是单继承,extends 关键字后只能有一个类名,即只能有一个直接父类;interface 是单继承,extends 关键字后可以有多个 interface 名称。
如果一个类定义时没有使用 extends 关键字,则它的超类是 Object 类
Object
类是Java中所有类的根类,它定义了一些通用的方法,如toString()
、equals()
、hashCode()
等。因此,所有的Java类都最终是Object
类的子类,直接或间接地。
子类的代码中,可以直接访问所有符合访问控制规则的超类中的成员。
子类的构造方法总会调用超类的构造方法 。如果在子类的构造方法中,没有调用超类构造方法的语句,则编译器会插入调用超类无参构造方法的语句。
子类中明确调用超类构造方法时,使用 super 关键字。
需要时,子类中可以使用 super 关键字访问超类的成员变量或者成员方法。
可以把子类对象赋值给超类类型的变量。(向上转型)
可以使用子类类型的变量访问超类中符合访问规则的成员
如果把子类对象赋值给超类类型变量,则不能使用超类类型变量访问只在子类中定义的成员'
不属于和超类同一包中的类,无法通过子类变量来访问 protected 成员。
- 在同一包中的类:
- 类可以访问同一包中其他类的
protected
成员。
- 类可以访问同一包中其他类的
- 不同包中的子类:
- 子类可以访问其父类中声明为
protected
的成员。
- 子类可以访问其父类中声明为
- 不同包中的非子类:
- 非子类的类无法直接访问其它包中类的
protected
成员。
- 非子类的类无法直接访问其它包中类的
final class ClassName {...},则该类不能被继承
多态
-
重载:同一个类中多个方法具有相同的方法名,参数列表不同
-
覆盖:指子类中重新定义超类中已有的一个或者多个方法/以及实现接口中的方法。
- 覆盖是,子类中覆盖的方法只能扩大访问范围,不能限制的更小。所以实现接口的方法只能定义为
public
- 如果在某个类的方法前添加
final
关键字,则该方法不能被覆盖。
- 覆盖是,子类中覆盖的方法只能扩大访问范围,不能限制的更小。所以实现接口的方法只能定义为
-
隐藏:子类中定义了与超类中同名的成员变量,默认情况下,这个变量名指代子类的成员变量,称该超类变量被隐藏。
覆盖所产生的多态效应,特别的是指在变量为某超类类型,而实际对象为其子类对象时,调用被覆盖方法,执行实际对应子类对象方法。
object 类
Object 类是所有类的超类,因为所有类都是直接或间接继承自它。
Object 类中重点关注的方法:
- equals: 默认判单是否同一对象(比较内存地址),String中覆盖了它,判断字符串的内容。
- toString: 在对象变量被自动转换为字符串的情况下(例如:""+obj),返回对象的字符串表示。默认是一个与对象地址相关的数字/字符串。可以覆盖成有意义的字符串表示。
Java I/O(输入/输出)
控制台
输出:
java
System.out.println//打印输出并换行
System.out.printf//格式化输出
System.out.print//打印输出不换行
输入:
java
Scanner input = new Scanner(System.in);
//intput.nextXXX
String userInput = input.nextLine(); // 读取用户输入的一行字符串
int userNumber = input.nextInt(); // 读取用户输入的整数
input.close()
Files
java
//Path path = Path.of(<filepath>);
String content = "Hello,wotld!";
//Files.writeString(path,content);
//Files.writeString(path,content,StandardOpenOption.APPEND);
//Files.writeString(path,content,Charset.forName("UTF-8"),StandardOpenOption.APPEND);
PrintWriter
java
PrintWriter out = new PrintWriter("filename.txt","UTF-8");//Charset.forName("UTF-8")
//out.println
//out.printf
//out.print
//write,write(String s)
out.close();
异常
异常:在程序运行中发生的,导致程序不能正常执行的事件对象 Error 类和Exception类都继承自Throwable类,RuntimeException类是Exception类的子类
三种异常
- Error 一般无法恢复:比如磁盘环,导致无法读取文件
- RuntimeException:一般是逻辑错误,可以避免,如数组越界
- Exception 子类中除RuntimeException中的类:checked异常,一般可恢复,比如文件名不正确导致FileNotFoundException
抛出异常的关键字:throw ExceptionObj
异常处理原则:捕获或者声明
对于编译时检查,必须编写应对可能抛出的异常。有两种方式:
- 捕获异常,并根据具体情况,在 catch 块中写明出现异常时执行的代码。
- 在方法声明的(参数列表)后中使用 throws 关键字声明异常,交由上层调用者处理异常。(因为底层被调用方法对高层应用的相关信息了解较少,由上层的方法处理更合适,这个层次可能是多层)需要掌握的主要是相关的关键字以及语法句式。
第一种捕获异常的句式(try-catch-[finally]
):
java
try{
......
......
}catch(ExceptionType1 ex){
......
.......
}catch((ExceptionType2 ex){
......
........
}catch((ExceptionTypeN ex){
.....
....
}catch(Exception1|Exception2|ExceptionN ex){
...
.....
}
//[如果有类似文件等资源需要释放,添加finally子句
finally{
//finally块中的代码无论是否发生异常,都会执行。
//资源释放代码
}
第二种捕获异常句式(try-with-resources)
java
//try-with-resources 句式中,try()之间可以创建多个I/O对象(比如,有时同时需要读、写文件),中间用";"
try(StreamType1 objRef1 = new StreamType1(...);
StreamType2 objRef2 = new StreamType2(....)){
}catch(ExceptionType1 ex){
......
.......
}catch((ExceptionType2 ex){
......
........
}catch((ExceptionTypeN ex){
.....
....
}catch(Exception1|Exception2|ExceptionN ex){
...
.....
}
//[如果有其他非I/O流资源需要释放,添加finally子句
finally{
//finally块中的代码无论是否发生异常,都会执行。
//资源释放代码
}
可以通过继承 Exception 类创建自定义异常,使用 throw 关键字抛出
catch 语句是按照编码顺序进行匹配,所以,多个catch子句包含子类和父类异常时,子类catch语句应在前
finally子句总是被执行,所以应在finally子句中释放资源
try块中定义的变量在catch子句中无法访问
子类覆盖方法时,不能添加异常
如果自定义的方法中,有代码可能抛出 checked 异常,如果没有使用 try-catch 语句捕获,方法定义时必须使用 throws 关键字声明这些 checked 异常 vod method() throws exception1,exception2(...)
调用可能抛出异常的方法可以捕获,或者再次声明throws
线程和进程
进程:内存等计算资源分配单位(文件句柄)
线程:CPU 调度单位
并发: 并发是指多个任务在一段时间内同时执行,可能是交替执行,但在宏观上看起来是同时的。在并发模型中,多个任务可以在同一个时间段内启动、执行和完成。
并行:并行是指多个任务在同一时刻同时执行。在并行计算中,多个处理器或核心可以同时执行多个任务,提高计算速度。
并行是并发的一种特例
创建线程的两种基本方法
1. 继承 Thread 类
java
class Task extends Thread{
public void run(){
//
}
}
Thread taskRef = new Task();
taskRef.start();
2. 实现 Runnable 接口
java
class Task implements Runnable{
public void run(){
//
}
}
Thread taskRef = new Thread(new Task());
taskRef.start();
编程题
Hello World
java
public class HelloWorld{
public static void main(String[] args){
system.out.println("Hello world!");
}
}
编写Swing程序,显示一个空白窗口
java
import javax.swing.*;
public class EmptyWindow extends JFrame{
public EmptyWindow(){
setSize(1024,768);//设置窗口大小
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args){
SwingUtilies.invokeLater(
()->{
JFrame frame = new EmptyWindow();
frame.setVisible(true);//显示窗口
}
);
}
}
java
import javax.swing.*;
public class AddComponentDemo extends JFrame{
public AddComponentDemo(){
setSize(800,600);//设置窗口大小
//确保点击窗口关闭按钮时,程序能正常退出
setDefaultCloseOperation(EXIT_ON_CLOSE);
initComponents();
}
private void initComponents(){
inputField = new JTextField(); //创建输入框
//输入框左上角坐标(500,500),宽度180,高度25
inputField.setBounds(500,500,180,25);
bt = new Jbutton("按钮"); //创建按钮
//按钮左上角坐标(700,500),宽度60,高度25
bt.setBounds(700,500,60,25);
setLayout(null); //为了使得 setBound 能够正常工作,需要设置布局管理器为 null
add(bt); //添加按钮组件
add(inputField); //添加文本输入框组件
}
public static void main(String[] args){
SwingUtilities.invokeLater(
()->{
JFrame frame = new AddComponentDemo();
frame.setVisible(true);//显示窗口
}
);
}
private JButton bt;
private JTextField inputField;
}
java
import javax.swing.*;
public class AddComponentDemo extends JFrame {
private JButton bt;
private JTextField inputField;
public AddComponentDemo() {
setSize(800, 600); // 设置窗口大小
setDefaultCloseOperation(EXIT_ON_CLOSE); // 设置点击窗口关闭按钮时程序能正常退出
initComponents(); // 初始化组件
}
private void initComponents() {
inputField = new JTextField(); // 创建文本输入框
// 设置输入框左上角坐标(500,500),宽度180,高度25
inputField.setBounds(500, 500, 180, 25);
bt = new JButton("按钮"); // 创建按钮
// 设置按钮左上角坐标(700,500),宽度60,高度25
bt.setBounds(700, 500, 60, 25);
setLayout(null); // 为了使得 setBounds 能够正常工作,需要设置布局管理器为 null
add(bt); // 添加按钮组件
add(inputField); // 添加文本输入框组件
}
public static void main(String[] args) {
SwingUtilities.invokeLater(
() -> {
JFrame frame = new AddComponentDemo();
frame.setVisible(true); // 显示窗口
}
);
}
}
-
AddComponentDemo
类: 继承自JFrame
类,表示一个窗口。 -
initComponents
方法: 初始化窗口中的组件,包括文本输入框和按钮。通过setBounds
方法设置组件的位置和大小,通过setLayout(null)
禁用布局管理器,使得setBounds
能够正常工作。 -
main
方法: 使用SwingUtilities.invokeLater
来确保窗口在事件分派线程上创建,避免多线程问题。创建AddComponentDemo
的实例并显示窗口。// 添加按钮组件
add(inputField); // 添加文本输入框组件
}
public static void main(String[] args) {
SwingUtilities.invokeLater(
() -> {
JFrame frame = new AddComponentDemo();
frame.setVisible(true); // 显示窗口
}
);
}
}
AddComponentDemo
类: 继承自JFrame
类,表示一个窗口。initComponents
方法: 初始化窗口中的组件,包括文本输入框和按钮。通过setBounds
方法设置组件的位置和大小,通过setLayout(null)
禁用布局管理器,使得setBounds
能够正常工作。main
方法: 使用SwingUtilities.invokeLater
来确保窗口在事件分派线程上创建,避免多线程问题。创建AddComponentDemo
的实例并显示窗口。bt
和inputField
: 分别表示按钮和文本输入框的实例变量,可以在类的其他方法中使用。