vscode编码不匹配,源文件用UTF-8,但JDK默认使用GBK编译(Windows下常见),所以报”编码GBK的不可映射字符”,可以在PowerShell/cmd编译时加参数强制使用UTF
-8:
javac -encoding UTF-8 Filename.java
java Filename

Scanner类简介:
1、使用前导包入:import java.util.Scanner;
2、构造Scanner类对象,它附属于标准输入流System.in。
Scanner sc =new Scanner(System.in);
3、常用的next()方法系列(Scanner不能获取char字符类型):
nextInt():输入整数
nextLine():输入字符串
nextDouble():输入双精度数
next():输入字符串(以空格作为分隔符)

==比较的是两个对象的内存地址,而变量被创建的时候相当于在内存中开辟空间,内容一致但内存地址不一致,判断不相等。
在Java中判断两个字符串是否相等要使用equals方法——str1.equals(str2),如果str1等于str2则返回true。

arr.length表示数组长度

println()输出末尾携带换行符,print()不携带。

数组int[] scores={1,2,3}大小在创建时就固定了,括号里不填是让编译器自己判断所占空间大小。

八种数据类型(字符串不属于基本数据类型)

  1. byte b=127(范围-128~127)
  2. short s(范围-32768~32767)
  3. int i(范围-2^32~2^31-1)
  4. long l=1L(范围-2^63~2^63-1,数字后要加L(大写L不容易看错成1),通常可以省略L,int能够自动提升到long)
  5. float f=1.23f(数字后要加f)
  6. double d=1.23(不加)
  7. boolean boo=true
  8. char c=’好’(单引号)

表数范围小的可以向表数范围大的进行自动类型转换

a==b return true/false,而不return 0/1

a&&b(与:都为true,return true)
a||b(或:有一个true,return true)
!a(非:true return false)
a^b(异或:只有一个true,return true)

condition?value1(true):value2(false)三元运算符

运算符优先级别排序由高向低分别是:()、!、算术运算符、关系运算符、逻辑运算符、赋值运算符

switch(input){},python的switch input :才是冒号!

一个程序可以由多个文件组成,每个文件可以定义多个类,每个类包含方法和变量,必有一个主方法main()。main()方法必须有参数 String[] args,没有参数会导致程序无法运行。
如果程序中有public类,文件名必须与public类的类名完全相同,扩展名为.java。 组成程序的多个类中,必须有且只有一个主类(包含public static void main(String[] args)方法的类)。不允许在一个.java文件中声明多个public类。

标识符可以包含字母、数字、下划线和美元符号,不能包含#号,空格,连字符(-),不能以数字,等号(=)开头。

Java程序编译后生成的是面向JVM的字节码文件,扩展名为.class,字节码文件可以在任何安装JVM的平台上运行,体现了Java的”一次编译,到处运行”特性。

按位或(bitwise OR)运算。|(按位或)有1则1,&(按位与)全1则1,^(按位异或)不同则1。位数不够自补全0。

Java语言使用的是Unicode字符集,Unicode字符集中,每个字符在内存中占16位(2字节)。
Java先编译为字节码,然后由JVM解释执行,是编译解释型语言。str.length()。
不能直接将字符串赋值给char数组,应该用 char[] str = “”.toCharArray();
运行字节码文件时,使用java命令不加.class扩展名。机器不能直接识别字节码文件,它要经过JVM中的解释器边解释边执行。

Java只支持单继承(一个类只能继承一个父类),通过接口(interface) 实现多继承的效果(一个类可以实现多个接口)。支持分布式的网络应用,可透明地访问网络上的其他对象。支持多线程编程。与平台无关、可移植性好。

在运行字节码文件时,使用java命令,一定要给出字节码文件的扩展名.class

数组:t.length (属性,没有括号)
String:t.length() (方法,有括号)
集合:t.size() (方法,有括号)

类名 对象名 = new 类名();对象名.属性名 = 值;对象名.方法名();对象名.属性名
Java规定构造方法名必须与类名相同。构造方法不需要写返回值类型,且内部不能写return null。构造方法里写return;是可以的,但不能返回具体值(包括null)。不用void关键字声明(有void就变成普通方法了)。构造方法可以重载,一个类可以有多个参数不同的构造方法。构造方法只能用new关键字来调用创建对象。
Java有自动垃圾回收机制(GC),负责回收不再使用的对象所占用的内存。
new运算符返回的是对象的引用(地址),而不是对象本身。创建对象时,系统会自动调用匹配的构造方法进行初始化。实例方法中可以引用类变量(静态变量),因为类变量属于类,可以被所有实例方法访问。对象赋值是引用传递,两个变量指向同一个对象,因此具有相同的引用值。
在Java中,类中声明的方法必须定义在类体内,不能在类体外定义。类是对象的模板,也是一种引用数据类型。

如果没有写任何构造函数,编译器会自动生成一个无参构造函数;如果写了一个有参数的构造函数,编译器不会再帮你生成无参构造函数;如果你既想支持自定义构造、又想支持Class obj写法,就要手动写一个无参构造函数。
保证类可被默认实例化,允许框架/反射机制实例化对象,支持继承体系中父类默认调用。

@Override是注解(Annotation),意思是这个方法重写(override)了父类中的方法。不写@Override代码能运行,但编译器不会检查提醒方法签名写错、没有真正覆写父类方法。
Override(重写)表示在类中定义一个和父类方法”同名、同参数、同返回类型”的方法,但内部实现不同,用来覆盖父类版本。

Java中所有类都默认继承自Object类。

this是一个关键字,用来表示当前对象(即当前实例)。每当用new创建一个对象,系统就会在内存中分配一个新的实例,当这个对象在调用它自己的方法(比如c1.add(…))时,Java会自动传递一个”指向当前对象”的引用,这个引用就是this。

Java中,如果类里的属性(或方法)不显式声明访问修饰符(public、protected、private)那它的访问权限是:默认(default)访问级别,也称为包访问权限(package-private).

关键字final修饰变量表示一旦赋值,就不能再重新赋值修改。

修饰方法表示禁止被子类重写。
修饰类表示不能被继承。
public final int

例变量(类成员变量)自动赋初值0,局部变量无默认值,必须显式初始化。

子类虽然继承了父类的所有成员,但私有成员(private)无法直接访问。抽象类可以有构造方法,用于子类初始化时调用。只是不能被实例化。构造方法可以重载(参数不同),但不能继承。Java只支持单继承(一个类只有一个父类),但可以实现多个接口。Java不支持运算符重载(除了+可以连接字符串)。仅仅改变返回类型不构成重载,参数列表必须不同。一个类可以实现多个接口,但只能继承一个类。访问权限是由修饰符决定的,不会因为继承而改变。父类不能包含子类,只是子类继承父类。protected=同包+其他包的子类可访问。没有写public、protected、private的类,只能被同包访问。public表示对整个工程可见。构造方法只能给实例成员变量赋初值。实现接口的类不能是抽象类。

Java核心包中,提供编程应用的基本类的包是java.lang,paint()方法使用Graphics类型的参数,常量全部大写,一个.java文件中定义多个类时,只允许其中声明一个public类。Java支持分布式的网络应用,可透明地访问网络上的其他对象。/**…*/注释方法能够支持javadoc命令,Java源程序不是编译型的,而是编译解释型的。机器不能直接识别字节码文件,它要经过JVM中的解释器边解释边执行。

当子类创建对象时,要先调用父类构造器,不写super(…)时默认会调用super()(父类的无参构造),若父类没有无参构造,必须手动写super(…)。
当子类重写了父类方法,但还想用父类原来的方法时,可以用 super.xxx()。
this→指当前类对象,super→指父类对象

数组里每个元素的构造参数确实不同,但这是正常的,因为它们是不同类型的对象。每个构造器接收的参数数量和意义不同,因为类本来就不一样。数组只关心类型是否兼容(有没有继承关系),不管参数一样不一样。

  • 普通的for循环遍历
    for (int i = 0; i < staff.length; i++) {
    Employee e = staff[i];
    }
  • 简化的迭代器遍历
    for (Employee e : staff) {
    }

String和StringBuffer的区别主要在是否可变、线程安全、性能用途三个点。
String一旦创建内容就不能改,修改时会生成新对象。StringBuffer直接操作同一块内存,不重新建对象。
String不可变天然线程安全,StringBuffer内部方法有synchronized(线程安全)。

String类的compareTo()用来比较字符串大小的方法。质上是按字符的Unicode编码(包括ASCII范围)逐个比较来决定大小。ASCII 是 Unicode 的子集。

split去除空格x

1
2
3
String类自带的split()方法," "连续空格会被当成空字符串拆开,而"\\s+"把多个空白看成一个分隔符。
正则表达式中\s匹配任意空白字符(包括空格' ',Tab \t,换行 \n,回车 \r)。+的正则含义是一个或多个前面的字符,a+表示一个或多个 a,\d+表示一个或多个数字。
因为Java字符串有转义字符,想在字符串里写\,必须写\\,所以正则里的\s+实际要写"\\s+"。
1
2
3
4
// 字符串二进制转换为十进制,不必使用幂函数
for (int i = 0; i < str.length(); i++) {
ans = ans * 2 + (str.charAt(i) - '0');
}

String对象一旦被创建,其内容就不能被改变。在一个循环中反复进行字符串拼接,就会产生大量中间态的 String 对象,效率非常低。
StringBuffer对象是可变的。它的内部是可变的字符数组。

StringBuffer不能直接赋值给String,return buffer.toString()来解决。

charAt(int index) 获取指定索引位置的字符
length() 获取字符串长度
indexOf(String str) 查找指定子串第一次出现的索引位置
equalsIgnoreCase(String another) 比较两个字符串是否相等,忽略大小写差异
replace(char oldChar,char newChar) 将字符串中所有的旧字符替换为新字符
startsWith(String prefix) 检查字符串是否以指定的前缀开头
endsWith(String suffix) 检查字符串是否以指定的后缀结尾
toUpperCase() 将字符串中的所有字符转换为大写
toLowerCase() 将字符串中的所有字符转换为小写
substring(int beginIndex) 从指定索引开始截取字符串到末尾
trim() 去除字符串开头和结尾的所有空白字符

抽象类(Abstract Class)不能被实例化(不能直接new),主要作为其他类的父类(基类),可以包含抽象方法和普通方法,子类必须实现所有的抽象方法(除非子类也是抽象类)

抽象方法(Abstract Method)只有方法声明,没有方法实现(没有{}方法体),以分号结束,必须在抽象类中声明,子类必须重写所有的抽象方法。抽象方法必须加public和返回类型void,如public abstract void printMsg();

Java只支持类的单继承,但支持接口的多继承。多继承会带来所谓的 “菱形继承问题” (Diamond Problem)。如果多个接口中存在相同默认方法,子类必须显式重写以解决冲突。

interface(接口)是一种”行为规范”或”契约”,定义了一组方法(通常没有具体实现),规定了一个类”应该做什么”,但不关心怎么做。implements关键字表示类去实现接口。一旦实现接口,类就必须实现接口中定义的所有方法。

通过接口类型的引用,指向了一个具体实现类的实例。

接口默认不能有实现,成员变量默认是public static final(常量),不能有构造方法,类可以实现多个接口,定义”能做什么”的能力。
抽象类可以有具体方法和抽象方法,可以是普通实例变量,可以有构造方法,类只能继承一个抽象类,定义”是什么”的继承关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class A {
public abstract void function(); // 抽象方法
}

public class B extends A {
@Override
public void function() {
;
}
}

public interface A {
void function();
}

public class B implements A {
@Override
public void function() {
;
}
}

throw:语句,用在方法内部
主动抛出异常对象,用在方法体内部,后面必须跟一个异常对象(new 出来的),执行到 throw 时方法会立即结束并抛异常
代码运行到这里时,我立即抛出这个异常对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
进入方法


执行代码逻辑

├── 条件满足?
│ │
│ ├─ 否 → 继续执行后续代码
│ │
│ └─ 是
│ │
│ ▼
│ 执行 throw
│ │
│ ▼
│ 方法立即结束
│ │
│ ▼
└────→ 异常抛给调用者

throws:方法声明的一部分,把异常往外”抛给调用者处理”
写在方法名后面,后面跟的是异常类型(不是对象),告诉调用者:这个方法可能抛这些异常,调用者需要负责处理或继续上抛
这个方法可能产生某类异常,调用者自己负责处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
调用方法 A() ────────────────┐

方法 A() 声明了 throws XxxxException


方法 A 内部可能产生异常?

┌────────────┴─────────────┐
▼ ▼
否(未产生异常) 是(产生了异常)
│ │
▼ ▼
正常执行后续逻辑 异常被抛出
│ │
▼ ▼
方法 A 正常返回 调用者必须 try/catch 或继续 throws

try/catch是异常处理机制
运行try里的代码→如果发生异常→自动跳到catch执行。
出现运行时错误(如除0),程序不会崩,而是进入catch
finally的意思是无论try或catch是否执行、抛异常、return,都一定会执行finally中的代码,把无论如何都要执行的代码从try/catch中抽出来,可以避免try或catch的末尾,导致重复

返回类型为void的方法中return;是合法的
所有的异常类皆继承java.lang.Throwable类

1
2
3
4
5
      Object
|
Throwable
/ \
Exception Error

java.io是Java 提供的 输入/输出(Input/Output)库
BufferedReader带缓冲的字符输入不在java.lang里,必须显式导入
在import java.io.*中,星号的含义是导入该包下的所有类,但不会导入子包

BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
System.in读的是字节(byte),而BufferedReader基于字符流内部读的是char[],所以才能提供readLine() 这样的”按行读取字符”的功能。为了能让BufferedReader使用键盘输入,必须先把字节变成字符

readLine()的方法签名是public String readLine() throws IOException,意思是读数据的时候可能失败,使用时必须负责处理。所以在main()里调用它Java会如下,强制在自己处理(try-catch)和不处理把责任往上抛(throws)中二选一。

1
2
3
4
5
6
7
try {
keyin.readLine();
} catch (IOException e) {
...
}

public static void main(String[] args) throws IOException

FileOutputStream用于向文件写入字节数据,FileInputStream用于从文件读入字节数据,都属于 java.io 包

FileInputStream file = new FileInputStream(“input.txt”) //读取文件
byte1=file.read() //返回下一个字节(0–255),没有更多返回 -1

InputStreamReader、BufferedReader、FilterReader 都属于字符流(Reader体系),FileInputStream 属于字节流(InputStream体系),不是字符流

Writer是字符流的顶层类,字符流以Unicode字符为处理单位,DataInputStream、PipedInputStream 是字节流,不处理 Unicode,BufferedReader是字符流,但它主要用于缓冲读取,并不是专门”用于处理 Unicode”的基础类

使用标准输入输出如System.in、System.out使用时常与I/O相关类(如InputStreamReader、BufferedReader)配合,需要导入import java.io.*;

字符流与字节流的主要区别在于每次读写的字节数不同,字节流(InputStream/OutputStream)以字节(8-bit)为单位,字符流(Reader/Writer)以字符(16-bitUnicode)为单位,每个字符占两个字节(理论上Java字符为UTF-16)

实现字符流的写操作类是Writer,实现字符流的读操作类是FileReader,FileInputStream是字节输入流,FileOutputStream是字节输出流

构造BufferedInputStream的合适参数是FileInputStream,构造参数必须是InputStream类型

Java存在两个不同的标准输出流,标准输出System.out和标准错误输出System.err
Serializable是标记接口(Marker Interface),没有方法,仅用于表示对象可被序列化,空接口
文件缓冲流如BufferedInputStream、BufferedOutputStream能减少物理I/O次数,提高效率
序列化就是把对象状态转换为字节流,可以存储到文件或通过网络传输

catch(Exception e)捕获所有Exception及其子类,范围最广
catch(IOException e)只捕获IO操作相关的异常,更具体准确

catch(IOException e){
e.printStackTrace(); //输出堆栈,便于调试,不会把异常默默忽略掉
}

为什么要把File传给FileReader/FileWriter?
FileReader需要知道要读取哪个文件
BufferedReader/BufferedWriter本身不负责文件读写,它们是包装器,依赖底层读写对象。
FileReader才是真正操作文件(读取字节→字符),BufferedReader只提供缓冲+readLine()

java.io与java.util.Scanner差异
java.io用于原始输入,更底层,不带解析格式的功能,性能更高
java.util.Scanner用于格式化输入,按各种类型自动解析,因为带解析器、有正则、类型判断,性能开销更大

JPanel和JApplet的默认布局管理器是AFlowLayout
Swing组件必须添加到Swing顶层容器相关的内容面板上
与同一个页面中的Applet通信不属于Applet安全限制
Applet必须继承自java.awt.Applet
为了向一个Applet传递参数,可以在HTML文件的APPLET标志中使用PARAM选项。在Applet程序中获取参数时,应使用的方法是getParameter()
Swing组件可直接添加到顶级容器中,要尽量使用非Swing的重要级组件,Swing的Jbutton不能直接放到Frame上
Applet程序用户自定义的Applet子类中,常常重载paint()方法在Applet的界面中显示文字、图形和其他界面元素
Swing包中的组件处理事件时,Swing包中的组件也是采用事件的委托处理模型来处理事件的
浏览器中执行Applet程序四个方法里最先执行的是init()
容器类java.awt.container的父类是.java.awt.Component
编译Applet源程序文件产生的字节码文件的扩展名为class

完整的Applet生命周期方法是:
init():初始化,首次加载时调用,用于初始化
start():启动,每次重新激活Applet时调用,例如用户访问页面时
stop():停止,Applet不再显示时调用,比如用户离开页面
destroy():销毁,Applet被销毁时调用,用于释放资源

Java事件处理包括建立事件源、事件监听器和将事件源注册到监听器
建立事件源:即产生事件的组件(比如按钮、文本框等)
事件监听器:即监听某个事件发生的具体处理方法,它通过实现对应的事件监听接口(如ActionListener、MouseListener等)来定义事件发生时的响应
注册监听器:将事件监听器绑定到事件源上,使得事件源的变化能够触发相应的监听器响应

Swing的事件处理机制包括事件源、事件和事件监听者
事件源:产生事件的组件(如按钮、文本框等)
事件:事件是对用户操作或程序变化的描述,比如点击按钮、鼠标移动等
事件监听者:监听并处理事件的对象。事件监听者通过实现相应的事件监听接口(如ActionListener、MouseListener等)来接收并响应事件

Swing事件处理是基于Java的事件处理机制实现的,但Swing事件处理更加侧重于图形界面组件的交互

JFrame由一个玻璃面板、一个内容面板和一个可选择的菜单条组成
玻璃面板(Glass Pane):最上层面板,通常用于显示覆盖整个窗口的组件,比如拖拽效果、特殊的UI装饰等。可以设置透明或者用于捕获鼠标事件
内容面板(Content Pane):核心面板,所有的Swing组件(如按钮、标签、面板等)都会添加到这个面板中。默认情况下,Swing组件添加到内容面板上,而不是直接添加到JFrame本身
菜单条(Menu Bar):可选,用于显示窗口顶部的菜单项(如“文件”、“编辑”等菜单)。如果需要菜单条,可以通过setJMenuBar()方法设置

与显示相关的Applet方法有paint()、repaint()和update()
paint():这是用于在Applet或组件上绘制内容的方法。每当窗口需要重新绘制时(如窗口大小变化、最小化后恢复等),系统会调用paint()方法。开发者可以在paint()方法中编写绘制逻辑(例如绘制图形、文字等)
repaint():这是请求重新绘制界面的一个方法。它实际上会触发update()和paint()方法的调用,通常用于需要更新界面时(如用户操作时界面元素变化)
update():update()方法是paint()的一个辅助方法,它负责首先清除之前的内容,然后调用paint()方法进行重新绘制。默认情况下,update()会调用paint(),但你可以重写它来自定义绘制流程

Applet可以运行在浏览器中,不能运行本地机器上的可执行程序,不能够存取客户机磁盘上的文件,只能在图形界面下工作

getCodeBase()返回Applet类文件(.class文件)所在的URL地址。通常这是加载Applet的Java类文件的路径
getDocumentBase()返回HTML文件(即包含Applet的网页)的URL地址。这是加载包含Applet的HTML页面的地址

java每个事件类都只对应一个事件
一个容器中不可以混合使用多种布局策略,可以嵌套其他容器
使用BorderLayout布局管理器时,GUI组件可以按任何顺序添加到面板上
Swing用户界面的程序设计中,容器可以被添加到其他容器中去

Java中没有提供检测与避免死锁的专门机制,但应用程序可以采用某些策略防止死锁的发生,对共享数据操作的并发控制是采用加锁技术,线程之间的交互,提倡采用suspend()/resume()方法,共享数据不一定必须定义为private,关键是对共享数据的访问需要加以控制,通常是通过加锁(例如synchronized)来避免并发访问冲突

synchronized可以对对象加互斥锁
线程在生命周期中要经历五种状态,若线程当前是新建状态,则它可以到达的下一个状态是可运行状态
一个类不能同时继承自一个类并实现同一个接口

线程的生命周期有五种状态:新建、可运行、运行、阻塞、终止。

虚拟机(JVM)中的线程调度器负责管理线程,调度器把线程的优先级分为10个级别,分别用Thread类中的类常量表示。每个线程的优先级都在常数1和10之间,即Thread.MIN_PRIORITY和Thread.MAX_PRIORITY之间。如果没有明确地设置线程的优先级别,每个线程的优先级都为常数8
多线程程序的执行结果可能受硬件、操作系统调度策略、JVM实现等因素影响,因此结果不是完全确定的
Java不支持多继承一个类继承自Thread类不能再继承其他类
线程执行run()方法后线程的生命周期自动结束
线程同步指保证多个线程对共享资源的访问时不会发生竞态条件(racecondition)。并不是所有线程都必须访问同一个synchronized方法,而是通过锁机制保证访问共享资源时的互斥
start()方法用于启动线程,它会使线程进入可运行状态,等待线程调度器分配CPU资源

在 UDP 通讯中,DatagramSocket 类的 receive(DatagramPacket p) 方法用于接收发送到该套接字绑定的本地端口的数据包。接收到的 DatagramPacket 对象中包含了发送方的网络地址、端口以及实际数据,因此它是基于网络地址与端口来接收并识别数据的

Socket 类的 getOutputStream() 方法返回一个 OutputStream 对象,程序可以通过这个流向服务器或客户端写出数据。虽然在 Java 中 Writer 和 Stream 有所区别,但在该题目的选项语境下,“写出器”对应的是输出流的功能。

URL 类的 getHost() 方法用于获取该 URL 对象所表示的资源所在的主机名称(例如www.example.com)

TCP 网络编程中,客户端使用 java.net.Socket 类来指定服务器的 IP 地址和端口号,从而发起连接请求。ServerSocket 是服务器端使用的

服务器端需要使用 java.net.ServerSocket 类来绑定一个特定端口,并通过 accept() 方法进入阻塞状态,等待并监听客户端的连接请求

java.io.File

File 类能判断文件是否存在,获取路径、大小,删除文件,创建目录,不能修改文件内容或属性(如修改文件只读/权限等)

方法 返回类型 说明
exists() boolean 是否存在
canRead() boolean 是否可读
canWrite() boolean 是否可写
isHidden() boolean 是否为隐藏文件
getAbsolutePath() String 获取绝对路径
getPath() String 获取构造File时使用的路径字符串
getName() String 获取文件或目录名
length() long 返回文件长度(字节),目录返回0
lastModified() long 返回最后修改时间(毫秒级时间戳)
isDirectory() boolean 是否为目录
isFile() boolean 是否为文件
list() String[] 返回目录下文件/文件夹名称列表(仅名称)
listFiles() File[] 返回目录下文件/文件夹File对象列表
mkdir() boolean 创建单级目录(父目录不存在时失败)
mkdirs() boolean 创建多级目录(父目录不存在也会创建)
delete() boolean 删除文件或空目录
createNewFile() boolean 创建新文件(文件存在则返回false)
renameTo(Filedest) boolean 重命名文件或移动文件到新路径
getParent() String 返回父目录路径字符串
getParentFile() File 返回父目录对应的File对象
isAbsolute() boolean 判断是否为绝对路径
setReadOnly() boolean 将文件设为只读
setWritable(boolean) boolean 设置文件是否可写
setReadable(boolean) boolean 设置文件是否可读
setLastModified(long) boolean 设置文件最后修改时间