Java笔记
Java背景
1. 官网
- oracle java 文档 https://docs.oracle.com/en/java/index.html
 - oracle jdk下载 https://www.oracle.com/java/technologies/downloads/
 - openjdk https://openjdk.org/
 
2. java和JVM
- 
java是基于类的、纯粹的面向对象编程语言
 - 
java是解释执行类的语言
 - 
WORA(write once, run anywhere)
- java程序被称之为一次写入,到处运行
 - 只要系统上有JVM,就能运行java程序
 
 - 
相关
- 
.java - java的源码文件
 - 
javac - java的编译器
 - 
.class - 编译后的二进制数据文件
 
 - 
 

3. java版本
3.1 平台体系
- Java SE(Java Platform Standard Edition)。Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。
 - Java EE(Java Platform Enterprise Edition)。这个版本以前称为 J2EE。 开发企业级的应用
 - Java ME(Java Platform Micro Edition)。这个版本以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境.
 

3.2 JDK和JRE
- 
JDK - java development kit,java开发包,包含java开发工具和
JRE - 
JRE - java runtime environment, java运行时环境,包含java虚拟机和运行时库
 - 
场景
- 
开发 - JDK
 - 
运行 - JRE
 
 - 
 

3.3 历史版本
至本文档编写时,JAVA已经推出JDK20,但现在广泛使用的版本是JAVA8,官网上所显示的LTS版本如下
| 版本 | 维护时间 | 
|---|---|
| JDK8 | 2030.09 | 
| JDK11 | 2026.09 | 
| JDK17 | 2024.09 后续每年会有LTS | 
所以,没有特别的需求,JDK8就满足需求。
3.4 Oracle JDK和OpenJDK
- 
Oracle JDK - 甲骨文收购了java后,维护的java版本,不开源
 - 
OpenJDK
- 
甲骨文开源的java版
 - 
各公司使用这个版本进行二次开发得到自己的JDK,比如安卓的ART
 - 
去除了很多JAVA的类库,保留核心功能,相当于
纯净版Java 
 - 
 

3.5 环境配置
- 
IDE - 本课使用jetbrains的社区版idea作为IDE。
 - 
JDK - OpenJDK18
 
4. jar包
java的执行有两种方式:
- 执行源码
 - 执行编译后程序
 
Java编译后的程序后缀名为.jar, 也被称为jar包
4.1 打包
- 
打开
File->Project Structur - 
选择
Artifacts,点击+,选择jar->From Modules xxxx - 
选择主类,点击
Main Class后的图标,完事后点击OK![]()
 - 
回到主界面,菜单
build->build Artifacts,确认完成打包 
4.2 执行
执行默认的类
java -jar xxxx.jar
指定主类执行
java -cp xxx.jar 包名.类名
4.3 引入第三方jar包
- 打包一个jar包,不同的地方是选择
empty - 主程序创建一个文件夹
libs,然后将之前打包的jar包拷贝过来 - 在
Project structure中的module中将本地jar包导入 - 创建
artifacts,流程和之前的一样 
Java语言
1. java语法
java语法与c++语法高度相似,故本课程对于相同点只列出相关语法,对于不同点会详细讲解。
2. 基本数据类型
java并不像c++那样继承了c语言的"丰富"的数据类型,java只有有符号数据类型。
| 基本数据类型 | 大小 | 取值 | 
|---|---|---|
| boolean | true,false | |
| byte | 1 字节 | |
| char | 2 字节 | |
| short | 2 字节 | |
| int | 4 字节 | |
| long | 8 字节 | |
| float | 4 字节 | |
| double | 8 字节 | |
| void | 
2.1 var
- java的
auto,用于定义局部变量 
2.2  final
- 格式 
[访问权限] final 数据/方法/类 final类似于C++中的final和const的结合final拥有更广泛的应用范围, 可修饰数据, 方法和类- 按
final修饰后, 会具有不可变性不可变一旦初始化就不能被修改, 不会被编译器优化常量可以被编译器优化
 
| 修饰 | 意义 | 示例 | 
|---|---|---|
| 基本数据类型 | 不可修改 | private final int n = 0; | 
| 类类型 | 对象可以修改,不可再指向别的对象 | private Foo final foo = new Foo(); | 
| 方法 | 不可被覆盖 | public final void Foo(){} | 
| 类 | 不可被继承 | final class Foo{} | 
| 静态数据 | 可当做常量 | public static final int VAL = 0; | 
3. 运算符
java的运算符基本上与c++的是一样的。
java没有sizeof。
| 分类 | 运算符 | 
|---|---|
| 赋值 | = | 
| 算术 | +,-,*,/, %``+=,-=,*=,%=``++,-- | 
| 关系 | >,<,<=, >=,!=,== | 
| 逻辑 | &&,` | 
| 位操作 | &,` | 
| 三目 | ?: | 
| 类型转换(强转) | (新类型)原类型 | 
4. 流程控制
流程控制和c++是一样的。
| 分类 | 运算符 | 
|---|---|
| 分支 | if-else``if-else if-else``switch-case | 
| 循环 | while``do-while``for``for(范围迭代)``break``continue | 
goto | 
4.1 switch语句
- 
java中的
switch除了提供传统的分支流程控制功能外,还可以作为一种升级版的三目,即提供多重选择 - 
语法
- 
case标签- 
类型为char、byte、short或int的常量表达式
 - 
枚举常量
 - 
字符串字面量
 - 
多个字符串,用逗号分隔
 
 - 
 - 
yield关键字 - 用于返回赋值给变量的值。 
 - 
 
// 形式1
变量 = swith(选择){
    case 值 -> 表达式;
    case 值 -> 表达式;
    case 值 -> 表达式;
    default ->表达式;
};
// 形式2
变量 = swith(选择){
    case 值 -> {  表达式; yield 值;}
    case 值 -> {  表达式; yield 值;}
    case 值 -> {  表达式; yield 值;}
    default -> {  表达式; yield 值;}
};
5. 代码组织结构
- java程序逻辑上以包为单位
 - 一个包中包含多个类
 

- 
源码结构
- 
包名作为路径名
 - 
类名作为文件名
 
 - 
 - 
图示解析
- 
java的包名类似c++的命名空间,但不同的是,java的包名既是空间名,也是路径名
 - 
下面的程序中有两个包名,也就有两个路径
- 
/com/kr/base- 有两个文件- 
Foo.java - 
Test.java 
 - 
 - 
/com/kr/core- 有两个文件- 
Foo.java - 
Test.java 
 - 
 
 - 
 
 - 
 

6. 类
6.1 格式
java的类与c++的类在语法上大体相同,区别在于访问权限需要写在java的类和成员前面。
- 
构造与类名相同,不需要析构
 - 
成员函数可以重载
 - 
访问权限 ,可选
- 
public - 
private - 
protected 
 - 
 - 
成员函数同样有
this指针 - 
静态成员 - 属于类,而非对象
 
[访问权限] class 类名{
	[访问权限] 成员;
	[访问权限] 成员;
	[访问权限] 成员;
    [访问权限] 成员;
    [访问权限] 成员;
    ....
}
public class Foo{
	public int n = 0;
    private float f = (float)0.0;
    String str = "hello world";
    static int n0 = 0;
    public void Test(){}
    private void Test(int){}
    static void Test(float){}
}
6.2 访问权限控制
| 关键字 | 权限 | 
|---|---|
public | 
共有 | 
private | 
私有 | 
protected | 
保护 | 
| 无 | 包权限,包内可以访问 | 
6.3 构造块和静态块
构造块- 无名的构造,实例化对象的时候调用静态块- 当类被解析的时候被调用- 时机 - 
静态块>>>构造块>>>构造 
class 类名{
    //这是构造块
    {
        //正常代码
    }
    //这是静态块
    static {
        //正常代码
        //只能访问静态成员
    }
}
6.4 包
包是java中库级的代码组织单位,高于类,等同于c++的命名空间。
- 
格式 -
package 包名;- 
package语句必须放是文件第一行非注释代码,表明本文件所属的包 - 
包名如果有多个层级,中间使用.隔开,同时是路径名 
 - 
 
比如,建立一个包名com.jlw.base

对应的文件夹路径
import
当其它类需要使用指定包中的类时,需要使用import语句
- 格式1 - 
import 包名.类名,使用指定包中的指定类 - 格式2 - 
import 包名.*,*是通配符,使用指定包中的所有类 
import com.jlw.base.Foo;
public class Main {
    public static void main(String[] args) {
        Foo foo = new Foo();
        //Test test = new Test(); //报错
    }
}
import com.jlw.base.*;
public class Main {
    public static void main(String[] args) {
        Foo foo = new Foo();
        Test test = new Test();
    }
}
7. 继承和多态
7.1 继承
- 语法
- 继承关键字 
extends - 不允许多继承
 
 - 继承关键字 
 
public class Base{
	void foo(){
		System.out.println("Base.foo()");
	}
	public int n;
}
public class Derived extends Base{
}
		public static void main(String args){
		Derived d = new Derived();
        d.n = 100;
        d.foo();
    }
- 调用父类构造
 
public class Base{
    Base(){}
    Base(int n){
        this.n = n;
    }
	void foo(){
		System.out.println("Base.foo()");
	}
	public int n;
}
public class Derived extends Base{
    Derived(){}
    Derived(int n){
        // 在带参构造子类时,默认调用父类的无参构造
        // 需要调用父类带参构造
        super(n);
        
        n = 20;
        this.n = 10;
        super.n = 30;
    }
}
super可当做父类的类名, 子类通过super关键字访问父类的成员n = 20;修改的是传入参数的值this.n = 10;修改的子类的值super.n = 30;修改的父类的值
instanceof运算符
用于判断某个对象是否是某个类的对象 ( 是否满足该继承体系 )
返回值
boolean
b = new Derived2();
boolean bIs = b instanceof Derived2;	// true
bIs = b instanceof Derived;				// false
bIs = b instanceof Base;				// true
- 隐藏
 
- 子类会隐藏父类同名数据, 如需指定父类数据, 可使用
super 
7.2 多态
- 语法
- 函数声明相同, 直接在子类重写, 不需要加关键字就可实现多态
 
 
public class Derived extends Base{
    void foo(){
        System.out.println("Derived.foo()");
    }
}
	public static void main(String args){
		Derived d = new Derived();
        d.n = 100;
        d.foo();
        
        Base b = new Derived();
        b.foo(); // 调用子类foo函数,自动实现多态
    }
快捷键Ctrl + O快速查看可重写的父类方法, 重写函数上可以添加@Override注解
当子类构造调用到父类构造时, 父类构造调用了子类重新函数foo(); 此时会访问到子类的foo函数, 所以我们不能再父类构造中调用到子类重写的函数
public class Base{
    Base(){}
    Base(int n){
        this.n = n;
        //this.foo(); 	// 子类走父类构造时,调用到了子类重写的foo函数
    }
	void foo(){
		System.out.println("Base.foo()");
	}
	public int n;
}
为了防止父类的部分函数被子类重写, 我们有种方法防止被子类重写
final关键字
public final class Base{	// 类不能被继承
    Base(){}
    Base(int n){
        this.n = n;
        //this.foo(); 	// 子类走父类构造时,调用到了子类重写的foo函数
    }
	final void foo(){	// 函数不能被重写
		System.out.println("Base.foo()");
	}
	public int n;
}
final关键字类似于C++的const, 但是比const的使用范围广, 添加到类前, 则该类不允许被继承, 添加到方法前, 则该方法不允许被重写
7.3 祖宗类
Object
- 
java所有的类都继承自
Object- 
toString用于输出对象信息 - 
equals用于判断对象是否相同- 判断类类型需要重写, 否则只能判断基本数据类型和String类型
 
public boolean equals(Object obj){ Foo foo = (Foo) obj; // 需要强转为该类类型,祖宗类无法访问Foo类数据成员 return n == foo.n; } - 
clone用于深拷贝 
 - 
 
8. 抽象类和接口
8.1 抽象类
java可以定义抽象类, 关键字abstract, 该关键字也可以用于定义抽象方法(C++的纯虚函数)
[访问权限] abstract class 类名{
	[访问权限] abstract 返回值 方法名(参数列表) {
        // 抽象方法
    }
    [访问权限] 数据类型 变量;
}
8.2 接口
java允许定义一种更纯粹的抽象类, 称为接口, class关键字改为interface
- 定义
- 接口的成员函数不能有实现
 - 接口不能定义数据成员
 - 接口不能实例化对象
 
 - 实现
- java允许接口多重继承
public Derived implements Animal
 - 子类必须实现接口的所有成员函数
 
 - java允许接口多重继承
 
public interface Animal{
	public void Eat();
	public void Sound();
}
9. 内部类
从代码组织层级来看,类是定义在包级之下。

但java还支持将类定义到更小的组织单位中,比如类中,甚至方法中,统称为内部类。

9.1 内部类
内部类实际上就是一个类内部定义一个外部类的引用, 这个引用必须有一个实例化的对象 ( 用于访问外部类的数据 )
- 内部类可以定义在其它类内,也可以定义在方法内
 - 内部类可以访问类外作用域的数据和方法,并无视权限
 
public class Foo {
    private int nFoo = 0;
    private void TestFoo(){
        System.out.println("Foo.Test");
    }
    //定义在类内
    public class Inn{
        public int nInn= 10;
        public void Test(){
            nFoo = 10; //访问外部数据
            TestFoo(); //访问外部方法
            System.out.println("Inn.Test");
            //定义在方法内
            class Inn3{
                public void Test(){
                    nInn = 20; //访问外部数据
                    nFoo = 30; //访问外部数据
                }
            }
        }
    }
}
- 当出现名称隐藏时,通过
类名.this的方式指定作用域 
public class Test {
    private int n = 0;
    
    class Inn{
        private int n = 0;
        public void Foo(){
            this.n = 8;      //访问自己的
            Test.this.n = 9; //访问Test的
        }
    }
}
- 内部类不能独立创建对象,必须使用外部类对象创建
 - 创建时不能直接
new,使用对象.new 
public class Outer {
    public class Inner{
    }
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner(); //创建内部类对象
    }
}
- 继承内部类没有意义, 不做讨论
 
9.2 匿名内部类
- 格式 - 
new 类名/接口名 (){} - 语义 - 创建一个无名类(继承自指定类,或者实现指定接口)对象
 - 匿名内部类可以定义数据成员
 - 一生只能定义一个对象
 
public class Outer {
    public interface Inter {
        public void Foo();
    }
    public void Foo(){
        System.out.println("Outer.Foo");
    }
    public static void main(String[] args) {
        //创建匿名类对象
        Outer outer = new Outer(){
            private int n = 0;
            public int n1 = 0;
            public void  Foo(){
                System.out.println("noname.Foo");
            }
        };
        outer.Foo();
        //创建匿名类对象
        Inter inter = new Inter() {
            @Override
            public void Foo() {
                System.out.println("Inter.Foo");
            }
        };
        inter.Foo();
    }
}
9.3 嵌套类
- 格式 - 
static class 类名{} - 说明 - 内部类使用
static修饰 - 不能访问外部的变量,可以直接创建对象
 
public class Outer {
    public static class Inner{
        public void Test(){
            System.out.println("Inner.Test");
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Outer.Inner inner = new Outer.Inner();
        inner.Test();
    }
}
10. 泛型
10.1 基本语法
- 类模板格式  - 
访问标号 类名<T>{} - 函数模板格式 - 
访问标号 返回值 函数名<T>{}- 意义不大
 
 
public class Foo <T>{
    private T val;
    private T Get(){
        return val;
    }
    private void Set(T val){
        this.val = val;
    }
    public static void main(String[] args) {
        Foo<String> foo = new Foo<String>();
        foo.Set("hello");
        System.out.println(foo.Get());
    }
}
10.2 类型擦除
java模板功能比c++的要弱。
在c++中,模板实例化后,模板的类型参数T便成为了具体的类型。
但在java中,模板实例化后,模板的类型参数T便成为了Object。
相当于模板内部将实例化模板的类型给擦除了。
package com.kr.testtem;
public class TestErase {
    static public class Foo{
        public void Test(){
            System.out.println("Foo.Test");
        }
    }
    static public class Tem<Foo>{
        public T obj;
        public Tem(T obj){
            this.obj = obj;
        }
        public void Call(){
            obj.Test();  //报错
        }
        public  void Test(){
        }
    }
    public static void main(String[] args) {
        Tem<Foo> tem = new Tem<>(new Foo());
        tem.Call();
    }
}
10.3 边界和通配符
- 边界
 
针对模板内部的类型擦除,java也做出了补偿,允许模板将T视作指定继承家族中的一员,即T都为指定类型的子类,从而在某种程度上调用类型的成员。
这种做法称之为为模板的类型指定边界。
- 格式 - 
<T externds 类名> 
package com.kr.testtem;
public class TestErase {
    static public class Foo{
        public void Test(){
            System.out.println("Foo.Test");
        }
    }
    static public class CSuperFoo extends Foo{
        public void Test(){
            System.out.println("Foo.Test");
        }
    }
    static public class Tem<T extends Foo>{
        public T obj;
        public Tem(T obj){
            this.obj = obj;
        }
        public void Call(){
            obj.Test();
        }
        public  void Test(){
        }
    }
    public static void main(String[] args) {
        Tem<Foo> tem = new Tem<>(new CSuperFoo());
        tem.Call();
    }
}
- 通配符
 
10.4 容器

11. 异常
- 
抛出异常 -
throw new 异常 - 
接收异常 -
try{}catch(异常){} - 
finally块 - 跟在在try后,无论是否有异常,都会执行finally - 
所有异常的父类都是
Exception - 
throws说明- 
所有方法,如果有未处理的异常,均要说明
 - 
格式 -
方法 throws 异常1,异常2 。。。 
 - 
 
package com.kr.testexp;
import com.kr.testtem.TestErase;
public class Test {
    //自定义异常
    static public class MyException extends Exception{
        public MyException(String str){
            super(str);
        }
    }
    //自定义异常
    static public class MyException2 extends Exception{
        public MyException2(String str2){
            super(str2);
        }
    }
    //方法异常签名
    public void Foo(int n) throws MyException, MyException2 {
        if (n>0){
            throw new MyException("test"); //抛出异常
        }else {
            throw  new MyException2("2");//抛出异常
        }
    }
    public static void main(String[] args) {
        Test t = new Test();
        //接收异常
        try {
            t.Foo(1);
        } catch (MyException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } catch (MyException2 e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally");
        }
    }
}
11.1 try…catch
public class Main(){
	public static void main(String[] args){
		try{
			throw new Exception("异常");
		}catch (Exception e){
			//System.out.println(e.toString());
            e.printStackTrace();
		}
	}
}
11.2 往外抛
加 throw Exception
	public class Foo{
		public void foo() throw Exception {
        	throw new Exception("异常");
    	}
    }
public class Main(){
	public static void main(String[] args) throw Exception{
        Foo foo = new Foo();
        foo.foo();
	}
}
12. 常用库类
- 字符串类 
String- java中所有的字符串都是String类对象
 - 文本块
"""\n""", 中间可以跨行,\用于换行拼接
 
 - 计算
Math - 数组
Array 
                    
                


                
            
        
浙公网安备 33010602011771号