1 基础
JavaSE:标准版
JavaME:移动端
JavaEE:企业版
1.1 注释
多行注释
/*
abc
def
ghj
*/
文档注释
/**
doc line1
doc line2
*/
1.2 基本数据类型
byte
short
int
long
float
double
boolean
char
各进制表示
int num_1 = 10; // 十进制
int num_2 = 010; // 八进制 以0开头
int num_3 = 0x10; // 十六进制 以0x开头
类型级别
用于类型转换
// 低 ----------------------------------------> 高
byte, short, char -> int -> long -> float -> double
类型导致计算溢出问题
int years = 20;
int money = 1e9; // 10亿
int res_1 = years * money;
System.out.println(res_1);
output:
-147xxxxxxxxx
结果溢出,因为int类型的最大范围到21亿,但结果为200亿
long res_2 = years * money;
System.out.println(res_2);
output:
-147xxxxxxxxx
仍然溢出,在years和money做乘法时已经溢出
long res_3 = years * ((long)money);
System.out.println(res_3);
output:
20000000000
结果正确! 提前将操作数做强制类型转换!
1.3 浮点数在金融业务中的问题
// 例1
float f = 0.1f; // 0.1
double d = 1.0 / 10; // 0.1
System.out.println(f == d) // 理论上输出为true
output:
false
思考:为什么会这样?
float d1 = 2313131313131313f;
float d2 = d1 + 1;
System.out.println(d1 == d2); // 理论上输出为false
output:
true
思考:为什么会这样?
答:浮点数存在舍入误差,当母数过大而改变量很小时,改变量被舍弃了。
所以金融业务中一般不用浮点数,而使用BigDecimal类
1.4 常量定义
final 关键字
final double PI = 3.14;
1.5 命名规则
驼峰法
- 类名:各单词首字母大写
- 变量名:第一个单词首字母小写,剩下的单词首字母大写
- 常量名:字母大写
1.6 位运算
运算速率极高!!!
按位与或非
A = 0011 1100 // 二进制
B = 1011 1001 // 二进制
-----------------------------
A & B = 0011 1000 //按位与
A | B = 1011 1101 //按位或
A ^ B = 1000 0101 //按位异或
~A = 1100 0011 //按位取反
按位左右移
2 * 8 = 16
2 << 3 = 16 // 把2左移3位
16 >> 3 = 2 // 把16右移3位
1.7 '+'与字符串
int a = 10;
int b = 20;
System.out.println(a + b);
System.out.println("" + a + b);
System.out.println(a + b + "");
output:
30
1020
30
字符串会带着后面的内容变为字符串
1.8 Javadoc文档注释
文件/类注释
手敲 /** IDEA自动补齐
/**
* @author liu
* @version 1.0
*/
public class Test{
...
}
方法注释
在方法头上方手敲 /**
public class Test{
/**
* @param name
* @return
* @throws Exception
*/
public String test(String name) throws Exception{
....
}
}
javadoc命令生成文档
- 使用cmd中javadoc命令
javadoc -encoding UTF-8 -charset UTF-8 doc.java
生成index.html即为文档
2. 使用IDEA生成JavaDoc文档
使用IDEA生成JavaDoc文档https://blog.csdn.net/m0_47176679/article/details/125381816
2 Java流程控制
2.1 Scanner-人机交互
java.util.Scanner对象获取用户的输入
import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if(scanner.hasNext()){
String str = scanner.next();
System.out.println(str);
}
scanner.close();
}
input: Hello World!
output: Hello
为什么不输出Hello World!只输出Hello? 见下例代码
import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if(scanner.hasNextLine()){
String str = scanner.nextLine();
System.out.println(str);
}
scanner.close();
}
input: Hello World!
output: Hello World!
hasNext() -> hasNextLine()
hasNext()只能读取到空白符之前的内容
hasNextLine()可以读取一行内容
通常简写(不做判断):
import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.nextLine();
System.out.println(str);
scanner.close();
}
Scanner判断输入数据类型
import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
if(scanner.hasNextInt()){
int num = scanner.nextInt();
System.out.println(num);
} else {
System.out.println("error");
}
scanner.close();
}
hasNextInt()、hasNextFloat() …
// 使用Scanner计算多个数字的和以及平均数
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
double sum = 0;
int m = 0;
while(scanner.hasNextDouble()){
double x = scanner.nextDouble();
m++;
sum += x;
}
System.out.println("sum:" + sum);
System.out.println("avg:" + sum/m);
scanner.close();
}
2.2 顺序结构
各行代码从上到下执行
2.3 选择结构
if-单选择
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
if(s.equals("Hello")){
System.out.println(s);
}
scanner.close();
}
if-双选择
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
if(s.equals("Hello")){
System.out.println(s);
}else{
System.out.println("oo");
}
scanner.close();
}
if-多选择
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int score = scanner.nextInt();
if(score < 60){
System.out.println("no ok");
}else if(score >= 60 && score < 80) {
System.out.println("so so ok");
}else{
System.out.println("ok ok");
}
scanner.close();
}
if-嵌套
if(a == b){
if(c == d){
xxxxxxx
}
}
Switch结构
// expe : byte or short or int or char or String
switch(expe){
case value1 :
xxxxx
break;
case value2 :
xxxxx
break;
default:
xxxxx
}
2.4 循环结构
while
while(expe){
xxxxx
}
do…while
循环至少执行一次
do{
xxxxxx
}while(expe)
for循环
for(int i=0; i<=100; i++){
xxxxxxx
}
九九乘法表:
public class Main {
public static void main(String[] args) {
for(int i=1; i<=9; i++){
for(int j=1; j<=9; j++){
if(j <= i){
System.out.print(j + "*" + i + "=" + i*j + '\t');
}
}
System.out.println();
}
}
}
output:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
增强for循环
用于遍历数组和集合
public class Main {
public static void main(String[] args) {
int[] a = {10, 20, 30, 40, 50};
for(int i : a){
System.out.println(i);
}
}
}
output:
10
20
30
40
50
for循环打印5行三角形
public class Main {
public static void main(String[] args) {
int blank = 5;
int num = 1;
for(int i=0; i<5; ++i){
for(int j=0; j<blank; ++j)
System.out.print(" ");
for(int j=0; j<num; ++j)
System.out.print('*');
num += 2;
--blank;
System.out.println();
}
}
}
output:
*
***
*****
*******
*********
3 Java方法
3.1 方法重载
相同函数名,但有不同类型或者不同个数的形参的函数(对函数返回值类型不做要求)
// 原函数
public class Main {
public static void main(String[] args) {
int a = 10;
int b = 20;
int result = max(a, b);
System.out.println(result);
}
public static int max(int a, int b){
return a>=b ? a : b;
}
}
如果修改main函数中a和b的变量类型?
程序会提示报错:double向int转换可能有损失!
// 编写针对double类型的max函数
public class Main {
public static void main(String[] args) {
double a = 10;
double b = 20;
double result = max(a, b);
System.out.println(result);
}
public static int max(int a, int b){
return a>=b ? a : b;
}
public static double max(double a, double b){
return a>=b ? a : b;
}
}
正常运行!
3.2 命令行传参
编写主函数代码
public class Main {
public static void main(String[] args) {
for(int i=0; i<args.length; ++i){
System.out.println("args[" + i + "]:" + args[i]);
}
}
}
命令行中编译java文件
PS D:\Program\Java\Java_Code\JavaSE> javac .\Base\src\Main.java
PS D:\Program\Java\Java_Code\JavaSE>
切换到项目所在的src目录下后,运行.class文件并向程序传参“Hello World”
PS D:\Program\Java\Java_Code\JavaSE\Base\src> java Main Hello World
args[0]:Hello
args[1]:World
PS D:\Program\Java\Java_Code\JavaSE\Base\src>
3.3 可变参数(不定项参数)
在函数定义时,在变量类型后面加(…),且只能是函数的最后一个参数。
public class Main {
public static void main(String[] args) {
test(1, 4, 7, 2, 3);
}
public static void test(int... i){
System.out.println(i[0]);
System.out.println(i[1]);
System.out.println(i[2]);
System.out.println(i[3]);
System.out.println(i[4]);
}
}
output:
1
4
7
2
3
4 Java数组
4.1 定义
在类型后面加 [ ]
int[] a = new int[10];
4.2 初始化方法
静态初始化
int[] a = {1, 5, 2, 10};
动态初始化
int[] a = new int[10];
a[0] = 10;
a[2] = 3;
4.3 遍历数组
普通for循环
int[] a = {1, 2, 3, 4, 5};
for(int i=0; i<a.length; ++i){
System.out.println(a[i]);
}
for each
int[] a = {1, 2, 3, 4, 5};
for(int i : a){
System.out.println(i);
}
for each只适用于遍历,不适用于对数组内容操作
Arrays类
int[] a = {1, 2, 3, 4, 5};
str = Arrays.toString(a);
b = Arrays.sort(a);
5 面向对象
5.1 三大特性
- 封装
- 继承
- 多态
5.2 构造器
即构造函数
public class Main {
//刚定义类时,无构造函数,默认为空构造函数
}
public class Main {
public Main() {
// Initial Operation
}
}
IDEA生成类构造器的快捷键:Alt + Insert
5.3 内存堆栈分析
// Pet
public class Pet {
String name;
int age;
public void shout(){
System.out.println("shout once!");
}
}
public class Main {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "wa";
dog.age = 4;
dog.shout();
Pet cat = new Pet();
}
}
上述程序内存情况如下:main函数在栈的最低部,变量名dog和cat被存放在“栈”中,指向的是“堆”中的空间,而堆中有一部分叫做方法区,每加载一个类,该类的信息被储存在其中,且静态方法区也在其中,可供所有对象调用。
5.4 getter与setter
public class Main {
private String name;
private int id;
}
此时,在外部不可使用对象访问这两个属性
可使用如下的set与get
public class Main {
private String name;
private int id;
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
}
此时可在类外通过调用get与set方法操作私有成员变量
IDEA同样提供Alt+Insert快捷键生成getter与setter
5.5 继承 extends
public class Person{
xxx
}
public class Student extends Person{
xxx
}
public class Teacher extends Person{
xxx
}
所有类都默认继承自Object类
5.6 super
super用于在子类中调用父类的信息
public class Person{
protected String name = "123";
}
public class Student extends Person{
private String name = "456";
public void test(String name){
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
public static void main(String[] args){
Student student = new Student();
student.test("789");
}
}
output:
789
456
123
实现了在子类中调用父类的信息
this vs super
this表示自身,super表示父类信息
5.7 方法重写
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();
A b = new B();
b.test();
}
}
class A{
public static void test(){
System.out.println("A->test()");
}
}
class B extends A{
public static void test(){
System.out.println("B->test()");
}
}
注意:本例中基类和派生类中两个test方法均为静态方法
output:
A->test()
A->test()
例2:去除test方法的static修饰符
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();
A b = new B();
b.test();
}
}
class A{
public void test(){
System.out.println("A->test()");
}
}
class B extends A{
public void test(){
System.out.println("B->test()");
}
}
output:
A->test()
B->test()
5.8 多态
基类指针可以指向子类对象
基类指针指向子类对象,而子类对象又重写了基类方法,在分别使用基类指针和子类指针调用该方法时,会存在不同情况。
5.9 instanceof
public class Main {
public static void main(String[] args) {
Object o = new Student();
System.out.println(o instanceof Student);
System.out.println(o instanceof Person);
System.out.println(o instanceof Object);
System.out.println(o instanceof Teacher);
}
}
class Person{
}
class Student extends Person{
}
class Teacher extends Person{
}
output:
true
true
true
false
5.10 类间转换
父类为高级,子类为低级,父转子可自动转,子转父需要强制。
public class Main {
public static void main(String[] args) {
Person person = new Student();
person.run(); // error!!!
}
}
class Person{
}
class Student extends Person{
public void run(){
System.out.println("student run");
}
}
class Teacher extends Person{
}
output:
error!!!
对父类引用做强制转换
public class Main {
public static void main(String[] args) {
Person person = new Student();
((Student)person).run();
}
}
class Person{
}
class Student extends Person{
public void run(){
System.out.println("student run");
}
}
class Teacher extends Person{
}
output:
student run
5.11 代码块
匿名代码块、静态代码块
public class Main {
{
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块");
}
public Main() {
System.out.println("Constructor");
}
public static void main(String[] args) {
Main main = new Main();
}
}
output:
静态代码块
匿名代码块
Constructor
多次初始化类对象??
public class Main {
{
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块");
}
public Main() {
System.out.println("Constructor");
}
public static void main(String[] args) {
Main main = new Main();
System.out.println("------------------------");
Main main2 = new Main();
}
}
output:
静态代码块
匿名代码块
Constructor
------------------------
匿名代码块
Constructor
5.12静态导入包
直接导入函数
import static java.lang.Math.random;
5.13 抽象类
定义函数,但并不实现,使用abstract关键字
abstract class A{
public abstract void test();
}
具体函数由继承它的子类实现
abstract class A{
public abstract void test();
}
class B extends A{
@Override
public void test() {
}
}
- 若子类也是抽象类,那么也不必实现函数,函数的实现由子子类负责。
- 抽象类只能被继承,不能被new实例化
- 受类的单继承机制限制,使用范围并不广泛
5.14 接口
接口中所有的定义都是抽象的,默认的修饰符都是public abstract
public interface Interface{
void run();
void add(String name);
}
实现接口:
public interface Interface{
void run();
void add(String name);
}
public interface Interface1{
void set(String name);
}
public class InterfaceImpl implements Interface, Interface1{
@Override
public void run() {
}
@Override
public void add(String name) {
}
@Override
public void set(String name) {
}
}
- 一个类可以实现多个接口。
- 实现接口的类必须重写接口的所有方法。
- IDEA提供快捷键Ctrl+I一键生成函数体。
5.14 内部类
public class Main {
private int id = 10;
public void test(){
System.out.println("Main func");
}
public class A{
public void test(){
System.out.println("A func");
}
public void getId(){
System.out.println(id);
}
}
public static void main(String[] args) {
Main main = new Main();
A a = main.new A();
a.test();
a.getId();
}
}
- A是Main的内部类
- 内部类可以访问外部类的私有成员变量
静态内部类
内部类使用static修饰
public static class A{
public void test(){
System.out.println("A func");
}
}
局部内部类
类在函数体中定义
public class Main {
public void method(){
class A{
public void show(){
System.out.println("Hello");
}
}
}
}
6 异常机制
异常:Exception
所涉及的关键字:try、catch、finally、throw、throws
6.1 异常捕获
public class Main {
public static void main(String[] args) {
int a = 1;
int b = 0;
try{
System.out.println(a / b);
}catch (ArithmeticException e){
System.out.println("Exception!!!!!!");
}finally {
System.out.println("Finally");
}
}
}
output:
Exception!!!!!!
Finally
finally通常用于善后工作,平时可有可无。
catch语句可出现多次
public class Main {
public static void main(String[] args) {
int a = 1;
int b = 0;
try{
System.out.println(a / b);
}catch (ArithmeticException e){
System.out.println("Exception!!!!!!");
}catch (Exception e){
System.out.println("666");
}finally {
System.out.println("Finally");
}
}
}
- 覆盖范围大的异常捕获要放在后面!!!
- Ctrl+Alt+T自动使用代码块包含语句
6.2 主动抛出异常
使用throw向外抛异常
public static void main(String[] args) {
int a = 1;
int b = 0;
if(b == 0){
throw new ArithmeticException();
}
try{
//xxx
}catch (){
}
}
D:\Program\Java\jdk-1.8\bin\java.exe -javaagent:D:\Program\IDEA-2023.3.4\lib\idea_rt.jar=55329:D:\Program\IDEA-2023.3.4\bin -Dfile.encoding=UTF-8 -classpath D:\Program\Java\jdk-1.8\jre\lib\charsets.jar;D:\Program\Java\jdk-1.8\jre\lib\deploy.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\access-bridge-64.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\cldrdata.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\dnsns.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\jaccess.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\jfxrt.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\localedata.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\nashorn.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\sunec.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\sunjce_provider.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\sunmscapi.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\sunpkcs11.jar;D:\Program\Java\jdk-1.8\jre\lib\ext\zipfs.jar;D:\Program\Java\jdk-1.8\jre\lib\javaws.jar;D:\Program\Java\jdk-1.8\jre\lib\jce.jar;D:\Program\Java\jdk-1.8\jre\lib\jfr.jar;D:\Program\Java\jdk-1.8\jre\lib\jfxswt.jar;D:\Program\Java\jdk-1.8\jre\lib\jsse.jar;D:\Program\Java\jdk-1.8\jre\lib\management-agent.jar;D:\Program\Java\jdk-1.8\jre\lib\plugin.jar;D:\Program\Java\jdk-1.8\jre\lib\resources.jar;D:\Program\Java\jdk-1.8\jre\lib\rt.jar;D:\Program\Java\Java_Code\JavaSE\out\production\Base Main
Exception in thread "main" java.lang.ArithmeticException
at Main.main(Main.java:12)
6.3 函数抛出异常
函数头中写throws
public class Main {
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
new Main().test(a, b);
} catch (ArithmeticException e) {
throw new RuntimeException(e);
}
}
public void test(int a, int b) throws ArithmeticException{
if(b == 0){
throw new ArithmeticException();
}
}
}
output:
Exception in thread "main" java.lang.RuntimeException: java.lang.ArithmeticException
at Main.main(Main.java:15)
Caused by: java.lang.ArithmeticException
at Main.test(Main.java:22)
at Main.main(Main.java:13)
6.4 自定义异常
只需继承自Exception类,然后跟着别的类的实现就行,一般用不上自定义的异常
class MyException extends Exception{
private int detail;
public MyException(int a){
this.detail = a;
}
public String toString(){
return "MyException{" + detail + "}";
}
}