Java SE相关知识点总结

Hello

  1. 新建java文件,后缀名为.java,文件名要和类名保持一致

    public class Hello{ //Hello是类
        public static void main(String[] args){ //main是方法,方法的括号里存放参数
            Syetem.out.print("Hello,py!")
        }
    }
    
  2. 编译

    在java文件目录下,使用 javac Hello.java 进行编译,生成class文件

  3. 运行

    运行java class文件,使用java Hello 运行

PS:

  1. java对大小写是敏感的;
  2. 文件名和类名要保持一致;
  3. 不能使用中文符号。

源代码经过编译,生成字节码,然后经解释器一句一句运行出来。

一、IEDA开发

快捷操作

psvm,生成一个main方法

sout,生成输出语句

Ctrl + Shift + Enter 快速补全分号

Ctrl+]或者Ctrl+[ 定位匹配大括号

Alt+Enter,new一个类后自动返回类对象定义

注释

单行注释://

多行注释:/* */

文档注释:/** */ 操作方法:/**回车

二、基础语法

2.1 标识符和关键字

2.1.1 关键字

java所有的组成部分都需要名字。类名、变量名、方法名都被称为标识符。

2.1.2 static关键字

public class Worker {
    private static int age;
    private double score;

    public void run(){
        go();           //非静态方法可以调用静态方法
    }

    public static void go(){

    }

    public static void main(String[] args) {
        Worker a = new Worker();
        a.score = 100;            //非静态变量需要使用“对象名.变量名”
        Worker.age = 18;          //类中的静态变量推荐使用“类.变量名”

        a.run();
        go();
    }
}
  • 静态代码块
public class Boss {

    //2:可以用来赋初值
    {
        System.out.println("匿名代码块");//匿名代码块
    }

    //1:只执行一次
    static {
        System.out.println("静态代码块");
    }

    //3
    public Boss() {
        System.out.println("构造方法");
    }

    public static void main(String[] args) {
        Boss boss = new Boss();
    }
}
运行结果:
静态代码块
匿名代码块
构造方法
  • 静态导入包
//静态导入包,
import static java.lang.Math.random;
import static java.lang.Math.PI;

public class Test {
    public static void main(String[] args) {
        System.out.println(random());
        System.out.println(PI);
        System.out.println(Math.max(1,2));	//没有静态导入max这个方法,就要以“类名.方法名”的方式使用
    }
}

2.1.3 标识符注意点

  • 标识符只能以字母、$、_ 三种符号为开头

  • 不能使用关键字作为变量名或方法名

2.2 数据类型

java是强类型语言,所有变量都必须下定义才能使用

2.2.1 数据类型的分类

基本数据类型
  • 数值类型:

整数:byte(1字节)、short(2字节)、int(4字节、默认的)、long(8字节)

浮点数:float(4字节)、double(8字节、默认的)

  • 字符类型:char(2字节)

  • boolean类型:值只有true和false,占1位

int最常用,long类型要在数字后面加一个L,float要在数字后面加一个F

引用数据类型

类、接口、数组

2.2.2 扩展

  1. 进制:二进制0b、八进制0、十六进制0x

  2. 最好完全避免用float进行比较,因为float存在舍入误差,如果需要进行计算,并且不能有误差,可以使用java的BigDecimal类

  3. 转义字符:\t 制表符 \n 换行 \r回车

2.2.3 类型转换

低 ---------------------------------------------------------------高

byte,short,char→ int → long → float → double

强制转换: (类型)变量名 高→低

自动转换: 低→高

注意点:

  • 运算中,不同类型的数据要先转换,再运算;

  • 转换时可能存在内存溢出、精度变化的问题;

  • 不能对布尔值进行转换;

  • 高容量转换到低容量的时候,需要使用强制转换。

2.3 变量

代表一块空间,位置是确定的,存什么东西是可以变化的

  • java变量是程序中最基本的存储单元,包括:变量名、变量类型和作用域;
  • java是一种强类型语言,每个变量必须声明其类型。
type varName [=value];
//数据类型 变量名 = 值;
//可以使用逗号隔开来生命多个同类型变量。

2.3.1 变量作用域

  • 类变量
public class Demo01 {
    static String str;	//str为类变量,在这个类中都可以调用

    public static void main(String[] args) {
        System.out.println(str);
    }
}

作用域是类,可以直接调用

  • 实例变量

    位于方法外边,类里边,从属于对象,如果不进行初始化,默认为该数据类型的默认值(所有的数字类型为0 ,布尔值为false,基本类型外的其他类型为null)

public class Demo1 {
    int age;	//age属于实例变量,从属于Demo1这个类,作用域要大于局部变量
	String name;
    
    public static void main(String[] args) {
        Demo01 demo1 = new Demo1();	//变量类型 变量名 = new Demo1()
        System.out.println(demo1.age);	//通过demo1来使用age这个实例变量
        System.out.println(demo01.name);
    }
}
运行结果:0
    	null

作用域为方法外,类里边,想要在方法中调用,需要new

  • 局部变量
public class Variable{
    static int a = 0;		//类变量,有个static
    String str = "hello";	//实例变量,位于方法外边,类的里边
    
    public void method(){
        int i = 0;	//局部变量,位于方法里边,必须生命和初始化值
    }
}

作用域为方法内部,必须声明和初始化值

2.3.2 常量

或叫做:静态变量,可以看做是一种特殊的变量,初始化后它的值不会发生变化

final 常量名 =;

2.3.3 变量的命名规范

  • 类成员变量:首字母小写和驼峰原则,helloWorld,lastName
  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字符和下划线,MAX,MAX_VALUE
  • 类名:首字母大写和驼峰原则,Hello,HelloWorld
  • 方法名:首字母小写和驼峰原则,main,mainTest

2.4 运算符

2.4.1 基础运算符

算数运算符:+, -, *, /, ,++, --,%
赋值运算符:=
关系运算符:>, <, >-, <=, ==, !=, instanceof
逻辑运算符:&&, ||, !   //与、或、非
位运算符:&, |, ^, ~, >>, <<, >>>
条件运算符:?, :
扩展赋值运算符:+=, -+, *=, /=
  • 运算时,若存在long类型的变量,结果也是long类型的;若存在double类型的,结构也是double类型的;否则为int类型。
  • 关系运算符返回的结果:true、false

2.4.2 自增、自减运算符

public class Demo {
    public static void main(String[] args) {
        int a = 3;
        int b = a++;	//先给b赋值,再自增
        int c = ++a;	//先自增,再给c赋值

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}
运行结果:5
		3
		5

幂运算 2^3,需要借助工具类进行操作

public class Demo {
    public static void main(String[] args) {
        double pow = Math.pow(2, 3);	//借助Math类中的pow方法
        System.out.println(pow);
    }
}
运行结果:8.0

短路运算

public class Demo {
    public static void main(String[] args) {
        int a = 10;
        boolean b = (a<6)&&(a++<13);	
        //与运算,第一个已经不满足,就不进行后面的运算,所以a没有自加

        System.out.println(a);
        System.out.println(b);
    }
}
运行结果:10
    	false

2.4.3 位运算符

A = 0011 1100
B = 0000 1101
A&B = 0000 1100	//相同位置都为1,才是1
A|B = 0011 1101	//有1则为1
A^B = 0011 0001	//相同为0,否则为1
~B = 1111 0010	//取反
<<左移 相当于*2
>>右移 相当于/2
    
public class Demo05 {
    public static void main(String[] args) {

        System.out.println(2<<3);//二进制中,左移三位,0000 0010→0001 0000
    }
}
运行结果:16

2.4.4 条件运算符和扩展赋值运算符

a+=b;	//a=a+b
a-=b;	//a=a-b

字符串连接符

public class Demo {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        System.out.println(""+a+b);
        //在+左侧出现了String类型,就会把其他操作数都转换成String并连接
        System.out.println(a+b+"");
        //在+右侧出现了String类型,左侧依然进行运算
    }
}
运行结果:1020

三元运算符

x ? y : z;
//如果x==true,则结果为y,否则为z

2.5 包机制

  • 用于区别类名的命名空间,包的本质等同于文件夹。
  • 一般利用公司域名倒置作为包名,com.baidu.www
  • import 导入包

2.6 JavaDoc

生成.class文件后,使用javadoc命令生成自己的API文档

javadoc -encoding UTF-8 -charset UTF-8 HelloWorld.class

-encoding 编码方式
-charset 字符集
参数信息

@author 作者名

@version 版本号

@since 指明需要最早只用的jdk版本

@param 参数名

@return 返回值情况

@throws 异常抛出情况

三、Java流程控制

3.1 用户交互scanner

用于获取用户输入的工具类,java.util.Scanner

  • 基本语法
Scanner s = new Scanner(System.in);

通过Scanner类的next()与nextLine()方法获取输入的字符串,在读取前一般需要使用hasNext()与hasNextLine()判断是否还有输入的数据。

3.1.1 基本方法的使用

  • next( )方法使用:
import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {

        /*创建一个扫描器对象,用于接收键盘数据*/
        Scanner scanner = new Scanner(System.in);	//new一个Scanner对象,并将其封装成scanner对象
        System.out.println("使用next方式接收:");

        /*判断是否有用户输入的字符串*/
        if (scanner.hasNext()){
            String str = scanner.next();    //使用next方法接收用户输入
            System.out.println("输入端内容为:" + str);
        }

        scanner.close();    //凡是属于IO流的类,使用结束后都要关闭
    }
}

运行结果:
使用next方式接收:
Hello py!
输入端内容为:Hello
  • nextLine( )方法使用:
import java.util.Scanner;

public class Demo02 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("使用nextline方式接收:");

        if (scanner.hasNextLine()){
            String str = scanner.nextLine();
            System.out.println("输出的内容为:" + str);
        }

        scanner.close();
    }
}
运行结果:
使用next方式接收:
Hello py!
输入端内容为:Hello py!

next()不能得到带有空格的字符串;nextLine()是以Enter为结束符,可以获得空白

3.1.2 scanner进阶用法

  • 判断输入数字类型:
import java.util.Scanner;

public class Demo04 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int i = 0;
        float f = 0.0f;

        System.out.println("请输入整数:");
        
        /*使用hasNextInt判断输入是否为整数*/
        if (scanner.hasNextInt()){
            i = scanner.nextInt();
            System.out.println("输入整数为:" + i);
        }else {
            System.out.println("输入不是整数!");
        }

        System.out.println("请输入小数:");
        
        /*使用hasNextInt判断输入是否为整数*/
        if (scanner.hasNextFloat()){
            f = scanner.nextFloat();
            System.out.println("输出小数为:" + f);
        }else {
            System.out.println("输入不是小数");
        }
    }
}
  • 求多个输入数字的和,并求平均
import java.util.Scanner;

public class Demo05 {
    public static void main(String[] args) {
        //输入多个数字,求和、求平均,每输入一个数字用回车确认,输入非数字结束输入
        Scanner scanner = new Scanner(System.in);

        double sum = 0;	//求和
        int m = 0;	//计算输入了多少个数字

        /*通过循环判断是否还有输入,并进行求和、统计*/
        while (scanner.hasNextDouble()){
            double v = scanner.nextDouble();
            m++;
            sum = sum + v;
            System.out.println("当前你输入的第"+m+"个数字为:"+v+"当前求和结果为:"+sum);
        }

        System.out.println("和为:" + sum);
        System.out.println("平均数为:" + (sum/m));

        scanner.close();
    }
}

3.2 顺序结构

Java的基本结构就是顺序结构,除非特别指明,否则所有指令都是按从上到下的顺序执行。

3.3 选择结构

使用 if 和 switch 进行选择

3.3.1 if单选择结构

  • 基本语法
if(布尔表达式){
    //如果布尔表达式为true则执行括号内的语句,否则直接跳过if
}
  • 单选择练习
import java.util.Scanner;

public class Demo01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        String s = scanner.nextLine();

        if (s.equals("py")){
            System.out.println("py");
        }

        System.out.println("End");

        scanner.close();
    }
}

3.3.2 if双选择结构

基本语法

if(布尔表达式){
    //如果布尔表达式的值为true
}else{
    //如果布尔表达式的值为false
}
  • 双选择练习
import java.util.Scanner;

public class Domo02 {
    public static void main(String[] args) {
        /*考试分数大于等于60分及格,否则不及格*/
        Scanner scanner = new Scanner(System.in);
        int score = scanner.nextInt();

        if (score>=60){
            System.out.println("考试及格");
        }else{
            System.out.println("考试不及格");
        }

        scanner.close();
    }
}

3.3.3 if多选择结构

  • 基本语法:
if(布尔表达式1){
    //如果布尔表达式1的值为true
}else if(布尔表达式2){
    //如果布尔表达式2的值为true
}else if(布尔表达式3){
    //如果布尔表达式3的值为true
}else{
    //如果以上布尔表达式的值都不为true
}
  • 多选择练习
import java.util.Scanner;

public class Demo03 {
    public static void main(String[] args) {
        /*每10分提供一个评级*/
        Scanner scanner = new Scanner(System.in);

        while(scanner.hasNextInt()){
            int score = scanner.nextInt();
            if (score==100){
                System.out.println("评分等级:A+");
            }else if (score>=90 && score<100){
                System.out.println("评分等级:A");
            }else if (score>=80 && score<90){
                System.out.println("评分等级:B");
            }else if (score>=70 && score<80){
                System.out.println("评分等级:C");
            }else if (score>=60 && score<70){
                System.out.println("评分等级:D");
            }else if (score>=0 && score<60){
                System.out.println("评分等级:不及格");
            }else {
                System.out.println("输入不合法");
            }
        }

        scanner.close();
    }
}

3.3.4 嵌套的if结构

在一个if或者if else语句里是可以使用if或者if else语句的。

  • 基本语法
if(布尔表达式1){
    //如果布尔表达式1的值为true
    if(布尔表达式1){
        //如果布尔表达式2的值为true
    }
}
  • 嵌套选择练习
import java.util.Scanner;

public class Demo04 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        int score = scanner.nextInt();
        if (score==100){
            System.out.println("满分");
        }else {
            if (score>60){
                System.out.println("及格");
            }else{
                System.out.println("不及格");
            }
        }

        scanner.close();
    }
}

3.3.5 switch多选择结构

判断一个变量与一系列值中的某个值是否相等,每个值称为一个分支。

  • switch语句中的变量类型可以是:

byte、short、int、char或者String

switch(表达式){
    case value1:
        //执行语句1
        break;	//可选
    case value2:
        //执行语句2
        break;	//可选
    default:	//可选
        //执行语句3
}
  • switch练习
public class SwitchDemo01 {
    public static void main(String[] args) {
        char grade = 'F';

        switch (grade){
            case 'A':
                System.out.println("优秀");
                break;
            case 'B':
                System.out.println("及格");
                break;
            case 'C':
                System.out.println("不及格");
                break;
            default:
                System.out.println("未知");
        }
    }
}
  • 如果不加break,可能存在一个case穿透的问题,假设满足B,而B没有break,就会输出"及格"和"不及格",所以每写一个case,在后面都要加一个break。

3.4 循环结构

3.4.1 while循环

while(布尔表达式){
    //循环内容
}
  • while循环练习
public class WhileDemo01 {
    public static void main(String[] args) {
        /*计算1~100的和*/
        int i = 0;
        int sum = 0;

        while(i<=100){
            sum = sum + i;
            i++;
        }
        System.out.println(sum);
    }
}
运行结果:
5050

3.4.2 do…while循环

do…while语句至少执行一次;

while先判断后执行,do…while先执行后判断。

do{
    //执行语句
}while(布尔表达式);
  • do…while循环练习
public class DoWhileDemo01 {
    public static void main(String[] args) {
        int i = 0;

        do {
            i++;
            System.out.println("第一次:"+i);
        }while(i<0);
    }
}
运行结果:
第一次:1

3.4.3 for循环

for循环执行的次数在执行前是确定的。

  • for循环执行流程:
  1. 最先执行初始化步骤。可以声明一种类型,但可以初始化一个或多个循环控制变量,也可以是空语句;
  2. 检测布尔表达式的值,如果为true,则执行循环体,如果为false,循环终止,开始执行循环体后面的语句;
  3. 每执行一次循环,更新一次控制变量;
  4. 再次检测布尔表达式的值,循环执行上面的过程。
  • 基本语法
for(初始化;布尔表达式;更新){
    //代码语句
}
  • for循环练习1
public class ForDemo02 {
    public static void main(String[] args) {
        /*计算0-100之间奇数偶数的和*/
        int oddsum = 0;
        int evensum = 0;

        for (int i = 0; i <= 100; i++) {
            if (i%2!=0){
                oddsum+=i;
            }else{
                evensum+=i;
            }
        }
        System.out.println("奇数和为:"+oddsum);
        System.out.println("偶数和为:"+evensum);
    }
}
运行结果:
奇数和为:2500
偶数和为:2550
  • for循环练习2
public class ForDemo03 {
    public static void main(String[] args) {
        /*循环输出1-100之间能被5整除的数字,每显示3个数字*/

        for (int i = 0; i <= 100; i++) {
            if (i%5==0){					//选出能被5整除的数字
                System.out.print(i+"\t");
            }
            if (i%(15)==0){					//第三个数字能被15整除
                System.out.print("\n");		//换行
            }
        }
    }
}

换行可以用两句话

System.out.print("\n");
System.out.println();
  • for循环练习3
/**
 * 1.使用for循环输出一个1-9;
 * 2.输出两个9的循环相乘;
 * 3.去掉重复的内容
 * 4.调整输出格式
 */
public class ForDemo04 {
    public static void main(String[] args) {

        for (int j = 1; j <= 9; j++) {
            for (int i = 1; i <= j; i++) {
                System.out.print(i + "*" + j + "=" + i*j +"\t");
            }
            System.out.println();
        }
    }
}
运行结果:
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循环

主要用于数组或集合

基本语法

for(声明语句:表达式){
    //代码句子
}
//声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配,作用域为for循环内,其值与此时数组元素的值相等。
//表达式:表达式是要访问的数组名,或者是返回值为数组的方法。

增强for循环练习:

public class ForDemo05 {
    public static void main(String[] args) {
        int i[] = {10,20,30};

        for (int x:i){		//把数组i全部赋给x,x的数据类型和i[]相同
            System.out.println(x);
        }
    }
}
输出结果:
10
20
30

3.5 break&continue

break用于强制退出退出循环,不执行循环中剩余的语句;

continue用于终止某次循环过程(跳过某次循环后继续执行下一次循环)。

3.5.1 break练习

public class BreakDemo01 {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            if (i==7){
                break;		//i=7的时候退出循环,但该方法依然可以执行
            }
            System.out.print(i);
        }
    }
}
运行结果:
123456

3.5.2 continue练习

public class BreakDemo01 {
    public static void main(String[] args) {
        for (int i = 1; i <= 9; i++) {
            if (i==7){
                continue;	//跳过i=7
            }
            System.out.print(i);
        }
    }
}
运行结果:
12

3.6 流程控制练习

练习1

/*输出1-20之间所有的质数*/
/*检验该数能否被自己和1之外的数整除即可,如果能整除并且不是自己,跳过该数字*/
public class LabelDemo01 {
    public static void main(String[] args) {
        for (int i = 2;i<=20;i++){
            for (int j = 2;j<=i;j++){
                if (i%j==0 && i!=j){    //能整除其他数,并且不是自己
                    break;				//如果能整除,跳出循环,执行i++
                }						//如果不满足该if,执行j++
                else if (i==j){			//直到满足i==j,
                    System.out.print(i + "\t");
                }
            }
        }
    }
}

练习2

public class TestDemo01 {
    public static void main(String[] args) {
        //打印三角形
        for (int i = 1; i <= 5; i++) {		//5行
            for (int j = 5; j >= i; j--){	//先打印每行前面的空白
                System.out.print(" ");
            }
            for (int j = 1; j <= i ; j++) {	//打印三角形的左半边
                System.out.print("*");
            }
            for (int j = 1; j <i ; j++) {	//打印三角形的右半边
                System.out.print("*");
            }
            System.out.println();
        }
    }
}
运行结果:
     *
    ***
   *****
  *******
 *********

四、Java方法

4.1 方法的概念

System.out.println()
 //System是一个类,out是一个对象,println()是一个方法
  • Java方法是语句的集合
  1. 方法是解决一类问题的步骤的有序组合
  2. 方法包含于类或对象中
  3. 方法在程序中被创建,在其他地方被引用

一个方法只完成一个功能

4.2 方法的定义和调用

方法类似于其他语言的函数

4.2.1 方法的组成部分

方法定义时,参数为形参,要在调用方法的时候将实参赋值给形参

实参和形参的数据类型要一一对应

修饰符	返回值类型 方法名(参数类型 参数名){
    …
    方法体
    …
    return 返回值;	//如果方法存在返回值,必须return返回,如果是void就不需要了
}
/**
 * 修饰符:public、static等
 * 返回值类型:有些方法没有返回值,这种情况下的类型为void
 * 参数类型:参数像是一个占位符,方法被调用时,传递值给参数,这个值为实参或变量
 * 方法体:具体的语句,定义该方法的功能
 */
public class Demo01 {
    public static void main(String[] args) {
        int sum = add(1, 2);	 //调用时,传值给形参,这里的1和2为实参
        System.out.println(sum);
    }

    public static int add(int a, int b){  //add方法的两个参数a和b均为形参
        return a+b;
    }
}
  • 方法练习
public class Demo02 {
    public static void main(String[] args) {
        int compare = compare(10, 20);	//1.传参  3.将返回值赋值给compare
        System.out.println(compare);
    }

    public static int compare(int a, int b){
        int maxnum = 0;

        if (a==b){
            System.out.println("a=b");
            return 0;		//return可以终止方法
        }

        if (a>b){
            maxnum = a;
        }else {
            maxnum=b;
        }
        return maxnum;		//2.传参后得到返回值maxnum
    }
}

4.2.2 方法调用

  • 调用方法:对象名.方法名(实参列表)

  • Java有两种调用方法的方式,根据方法是否有返回值进行选择。

  1. 方法有返回值的时候,方法调用通常会被当做一个值。例如:

    int larger = max(30, 40);
    
  2. 如果方法返回值为void,方法调用一定是条语句。例如:

    System.out.println("Hello!");
    
方法调用的两种方式
  1. 静态方法 static 关键字,使用 对象名.方法名() 的方式调用
//在Student类中定义了一个say静态方法
public class Student {
    public static void speak(){
        System.out.println("说话");
    }
}
//在Demo02类中调用上面定义的say方法
public class Demo02 {
    public static void main(String[] args) {
        Student.speak();	//类名.方法名()
    }
}
  1. 非静态方法的调用,要使用 new 关键字将类实例化
//在Student类中定义一个非静态的方法
public class Student {
    public void speak(){
        System.out.println("说话");
    }
}
//在Demo02类中调用上面定义的Student方法
public class Demo02 {
    public static void main(String[] args) {
        //先使用new将方法所在的类进行实例化
        //对象类型 对象名 = 对象值;
        Student student = new Student();
        student.speak();
    }
}
  • 在同一个类中,一个静态方法调用非静态方法会报错
//一个已经存在的方法肯定是不能调用一个还没有存在的方法的,所以直接调用b方法的时候会报错
public class Demo02 {
    public static void main(String[] args) {
        Student student = new Student();
        student.speak();
    }
    //静态方法,和类一起加载
    public static void a(){
        b();
    }
    //非静态方法,实例化之后才存在
    public void b(){

    }
}

4.2.3 值传递和引用传递

Java的本质是值传递

引用传递:传递对象,其本质还是值传递

public class Demo05 {
    public static void main(String[] args) {
        People people = new People();	//1.实例化People,定义为people
        System.out.println(people.name);    //返回null

        Demo05.change(people);
        System.out.println(people.name);    //返回lx
    }

    public static void change(People people){//将people传递给了change方法
        people.name = "lx";	//	change方法中people.name是有值的,指向的是People类中的name
    }
}

class People{
    String name;
}

4.3 方法重载

一个类中,两个方法的名字相同,但两个方法的==参数(形参)==不同。

  • 重载的规则:
  1. 方法名称相同;
  2. 参数列表必须不同(个数不同,类型不同,参数排列顺序不同等);
  3. 方法的返回类型可以相同也可以不同;
  4. 仅仅返回类型不同不足以成为方法的重载。
  • 实现理论:

方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法。

  • 方法重载练习
public class Demo03 {
    public static void main(String[] args) {
        int sum = add(1,2);
        System.out.println(sum);
    }

    public static int add(int a, int b){
        return a+b;
    }

    public static int add(int a, int b, int c){
        return a+b+c;
    }
}
运行结果:
3		//因为调用的时候,传了2个参数,匹配的是上面的add方法

4.4 命令行传参

在DOS窗口直接运行一个class文件,需要找到包的路径,在该包的根目录下运行class文件

4.5 可变参数

Java支持传递同类型的可变参数给一个方法

在方法声明中,在指定参数类型后加一个省略号(…)

一个方法中只能指定一个可变参数,必须放在所有参数的最后

public class Demo04 {
    public static void main(String[] args) {
        Demo04 demo04 = new Demo04();
        demo04.test(1,2,3,4);		//给可变参数i传递实参
    }

    public void test(int... i){		//这里的i就是可变参数
        System.out.println(i[0]);
        System.out.println(i[1]);
    }
}
运行结果:
1
2

4.6 递归

一个方法调用自己。

递归包含两个部分:

递归头:什么时候不调用自身方法

递归体:什么时候需要调用自身方法

public class Demo05 {
    public static void main(String[] args) {
        System.out.println(f(3));
    }

    public static int f(int i){
        if (i==1){		//f(1)就是递归的头,递归到f(1)时就停止递归了
            return 1;
        }else {
            return i*f(i-1);
        }
    }
}
运行结果:
6

五、Java数组

5.1 数组的定义

  • 数组是相同数据类型的有序集合;
  • 描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成;
  • 每个数据称作数组元素,通过数组下标访问。

5.2 数组的声明和创建

  • 数组声明的语法
dataType[] arrayRefVar;		//首选的方法
或
dataType arrayRefVar[];
  • 使用new操作符创建数组
dataType[] arrayRefVar = new dataType[arraySize];
  • 获取数组长度
arrays.length

数组练习1

public class Array01 {
    public static void main(String[] args) {
        int[] nums = new int[5];	//声明并创建数组
        nums[0] = 1;
        nums[1] = 2;
        nums[2] = 3;
        nums[3] = 4;
        nums[4] = 5;
        
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        System.out.println(sum);
    }
}
运行结果:
15

5.3 内存分析和三种初始化

内存分析

声明时,数组压入

new创建时,在中开辟空间

三种初始化

  • 静态初始化:创建+赋值
int[] nums01 = {0,1,2,3};
  • 动态初始化:包含默认初始化
int[] nums02 = new int[3];
nums02[0] = 10;
  • 默认初始化

数组被分配空间后,每个元素也按照实例变量同样的方式被隐式初始化。

5.4 数组的使用

  • 练习1

普通的for循环

public class Array03 {
    public static void main(String[] args) {
        int[] nums = {1,2,3,4,5};

        int max = nums[0];
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > max){
                max = nums[i];
            }
            System.out.println(nums[i]);
        }
        System.out.println("max="+max);
    }
}
  • 练习2

for-Each循环

public class Array04 {
    public static void main(String[] args) {
        int[] nums = {1,2,3,4};
        //没有下标,没办法操作数组元素
        for (int num : nums) {
            System.out.print(num);
        }
    }
}
运行结果;
1234
  • 练习3

数组作方法入参

public class Array04 {
    public static void main(String[] args) {
        int[] nums = {1,2,3,4};

        print(nums);
    }

    public static void print(int[] arrays){
        for (int i = 0; i < arrays.length; i++) {
            System.out.print(arrays[i]+" ");
        }
    }
}
运行结果;
1 2 3 4 
  • 练习4

数组作为返回结果

public class Array04 {
    public static void main(String[] args) {
        int[] nums = {1,2,3,4,5};

        int[] reverse = reverse(nums);
        printArray(reverse);
    }

    public static int[] reverse(int[] arrays){
        int[] result = new int[arrays.length];

        for (int i = 0, j = arrays.length - 1; i < arrays.length; i++,j--) {
            result[i] = arrays[j];
        }

        return result;
    }

    public static void printArray(int[] arrays){
        for (int i = 0; i < arrays.length; i++) {
            System.out.print(arrays[i]+" ");
        }
    }
}
运行结果:
5 4 3 2 1 

5.5 多维数组

多维数组可以看成是数组的数组

int a[][] = new int[2][5];
  • 多维数组的使用
public class Array05 {
    public static void main(String[] args) {
        int[][] array = {{1,2},{2,3},{3,4},{4,5}};
        for (int i = 0; i < array.length; i++) {
            for (int j = 0; j < array[i].length; j++) {
                System.out.print(array[i][j]+" ");
            }
        }
    }
}

5.6 Arrays类

  • 数组的工具类java.util.Arrays
  • Arrays类中的方法都是static修饰的静态方法,使用的时候可以直接使用类名进行调用
import java.util.Arrays;

public class Array06 {
    public static void main(String[] args) {
        int[] a = {1,22,4,55,783,4536,78};

        Arrays.sort(a);       //对数组进行排序:升序
        System.out.print(Arrays.toString(a));
    }
}
运行结果:
[1, 4, 22, 55, 78, 783, 4536]

5.7 冒泡排序

import java.util.Arrays;

public class Array07 {
    public static void main(String[] args) {
        int[] a = {1,22,4,55,783,4536,78};

        int[] sort = sort(a);
        System.out.print(Arrays.toString(sort));
    }

    //冒泡排序(升序)
    public static int[] sort(int[] arrays){
        int temp = 0;
        boolean flag = false;

        //外层循环,判断比较的次数
        for (int i = 0; i < arrays.length-1; i++) {
            //内层循环,将两个相邻数中较小的一个放到前面(设置一个临时变量,需要交换位置则将小的数放入临时变量)
            for (int j = 0; j < arrays.length-1-i; j++) {
                if (arrays[j+1] < arrays[j]){
                    temp = arrays[j];
                    arrays[j] = arrays[j+1];
                    arrays[j+1] = temp;
                    flag = true;
                }
            }
            if (flag==false){
                break;
            }
        }
        return arrays;
    }
}

5.8 稀疏数组

  • 二维数组中的许多元素值默认是0,不需要特别做记录,所以用稀疏数组解决。

  • 如果一个数组中大部分数字都是0或者都是相同的数字,就可以用稀疏数组来保存该

  • 稀疏数组的处理方式是:

    • 记录数组有几行几列,有多少个不同值;
    • 把具有不同值的元素的行、列和元素值保存在一个小规模数组中。

六、面向对象编程OOP

6.1 面向对象

  • 面向过程

步骤清晰简单,第一步做什么,第二部做什么

  • 面向对象

分类的思维,将问题分类后,对这些分类进行单独的思考

  • 本质

以类的方式组织代码,以对象的形式组织(封装)数据

  • 三大特性

    • 封装:包装数据
    • 继承:类之间
    • 多态:
  • 对象,是具体的事物,是类的具体实例。

  • 类,是对某一类事物的整体描述,是对象的抽象

6.2 对象的创建分析

使用new关键字创建对象

6.2.1 理解对象练习

public class Application {
    public static void main(String[] args) {
        //类实例化之后会返回一个自己的对象
        //lx、py对象就是Student类的一个具体实例
        //使用new关键字创建对象的时候,除了会给对象分配内存空间外,还会进行默认初始化,以及对类中构造器的调用。
        Student lx = new Student(); //lx和py是两个不同的对象
        Student py = new Student();

        lx.name = "lx";
        py.age = 18;
        
        System.out.println(lx.name);
        System.out.println(lx.age);
    }
}
运行结果:
lx
18
public class Student {
    //属性:字段
    String name;	//默认为null
    int age;		//默认为0

    //方法
    public void study(){
        System.out.println(this.name + "在学习java");
    }
}

一个类中,只能有属性和方法

6.2.2 构造器

  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的,构造器的特点:

    1. 必须和类的名字相同;
    2. 必须没有返回类型,也不能写void。
  • 构造器的作用:

    1. 使用new关键字,本质是在调用构造器
    2. 用来初始化对象的值
  • 注意点

    • 定义了有参构造后,如果想使用无参构造,需要显示定义一个无参构造
    • 无参构造在默认存在的
    public class Application {
        public static void main(String[] args) {
            Student student = new Student();
            System.out.println(student.name);
        }
    }
    
    public class Student {
        String name;
        
        //无参构造,显示定义(显示定义是指,在代码中将这行代码写出来)
        public Student() {
        }
    
        //有参构造,只要定义有参构造,无参就必须显示定义
        public Student(String name) {
            this.name = name;
        }
    }
    

快捷键:Alt + Insert

6.2.3 创建对象内存分析

import com.oop.demo03.Pet;

public class Application {
    public static void main(String[] args) {
        Pet dog = new Pet();

        dog.name = "阿福";
        dog.age = 1;
        dog.bark();
        System.out.println(dog.name);
        System.out.println(dog.age);
        
        Pet cat = new Pet(); 
    }
}
package com.oop.demo03;

public class Pet {
    public String name;
    public int age;

    public void bark(){
        System.out.println("哈哈哈");
    }
}

堆中有一个方法区用来加载类和方法以及其中的,在运行的时候,栈中有main方法,new一个对象之后,栈中会生成一个引用变量,这个引用变量指向堆中具体的对象,不同的对象具有不同的地址。

6.3 面向对象三大特征

6.3.1 封装

  • 程序要求”高内聚,低耦合“

  • 封装(数据的隐藏)

    通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这种方式称为信息隐藏。

  • 属性私有,get/set

  • insert + Ins快捷键插入get和set

封装代码说明

package com.oop.Demo04;

public class Student {
    private String name;	//属性私有
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age>120 || age<0){
            System.out.print("输入年龄不合法"+"\t");
            this.age = 3;
        }else {
            this.age = age;
        }
    }
}
import com.oop.Demo04.Student;

public class Application {
    public static void main(String[] args) {

        Student student = new Student();
        student.setName("lxpy");
        System.out.println(student.getName());

        student.setAge(1220);
        System.out.println(student.getAge());
    }
}

6.3.2 继承

  • 继承的本质是对某一批类的抽象

  • 子类继承父类,使用extends关键字,子类(派生类)是父类(基类)的扩展

  • Java中只有单继承,没有多继承

  • 在Java中,所有的类都默认继承Object类

  • 继承是类和类之间的一种关系,此外,类之间的关系还有依赖、组合、聚合等。

  • 快捷键:Ctrl + H,查看类间的继承关系

  • 修饰符和继承的关系:
    在这里插入图片描述

  • 继承练习1

public class Application {
    public static void main(String[] args) {

        Student student = new Student();
        student.say();
    }
}
public class Person {
    public void say(){
        System.out.println("你好");
    }
}
//子类继承父类,就会拥有父类的全部非私有成员
//private修饰的只能被本类的非静态的属性、方法使用。即使被继承,由于作用域的原因,依然无法被使用
public class Student extends Person {

}
super关键字
  • 继承练习2
import com.oop.Demo05.Student;

public class Application {
    public static void main(String[] args) {

        Student student = new Student();
        student.hello("py");
    }
}
运行结果:
py
liuxin
lx
package com.oop.Demo05;

public class Student extends Person {
    private String name = "liuxin";

    public void hello(String name){
        System.out.println(name);			//这里的name为形参,在Application中赋值为py
        System.out.println(this.name);		//this.name是Student类中的name
        System.out.println(super.name);		//super.name是父类Person中的name
    }
}
package com.oop.Demo05;

public class Person {
    protected String name = "lx";
}
  • 继承练习3
import com.oop.Demo05.Student;

public class Application {
    public static void main(String[] args) {

        Student student = new Student();
    }
}
运行结果:
Person无参执行
Student无参执行
package com.oop.Demo05;

public class Student extends Person {

    public Student() {
        //隐藏代码super():默认调父类的无参构造
        super();    //调用父类的无参构造,必须放在子类构造器的第一行
        System.out.println("Student无参执行");
    }
}
package com.oop.Demo05;

public class Person {
    public Person() {
        System.out.println("Person无参执行");
    }
}
  • 注意点
1. super调用父类的构造方法,必须在构造方法的第一行
2. super必须只能出现在子类的方法或构造方法中
3. super和this不能同时调用构造方法(这两个关键字必须放在构造方法的第一行,同时调用会报错)
  • 和this的比较
1. 代表的对象不同
   this:本身调用者这个对象
   super:代表父类对象的应用
2. 前提
   this:没有继承也可以使用
   super:只能在继承条件下才可以使用
3. 构造方法
   this:本类的构造
   super:父类的构造
重写
  1. 方法的调用只和等号左边定义的数据类型有关
import com.oop.Demo05.A;
import com.oop.Demo05.B;

public class Application {
    public static void main(String[] args) {

        B b = new B();		//数据类型是B
        b.test();
        
        //父类的引用指向了子类
        A a = new B();		//数据类型是A
        a.test();
    }
}
运行结果:
B的方法实现了
A的方法实现了
public class B extends A{
    //这里加了static关键字
    public static void test() {
        System.out.println("B的方法实现了");
    }
}
public class A {
    public static void test(){
        System.out.println("A的方法实现了");
    }
}
  1. 方法的重写
  • 重写都是方法的,和属性无关
  • 重写只和非静态方法有关,和静态方法无关
import com.oop.Demo05.A;
import com.oop.Demo05.B;

public class Application {
    public static void main(String[] args) {

        B b = new B();
        b.test();

        A a = new B();  //子类重写了父类的方法,所以调用的都是B中的方法
        a.test();
    }
}
运行结果:
B的方法实现了
B的方法实现了
public class B extends A{
    //Override 重写
    @Override   //注解:有功能的注释
    public void test() {
        System.out.println("B的方法实现了");
    }
}
public class A {
    public void test(){
        System.out.println("A的方法实现了");
    }
}
  • 总结
重写:需要有继承关系,子类重写父类的方法
	1.方法名必须相同,但方法体不同
	2.参数列表必须相同(不同的话会变成重载)
	3.修饰符:范围可以扩大但不能缩小
	  public > protected > default > private
	4.抛出的异常:范围可以缩小但不能扩大

快捷键:Alt + Insert,选择override

6.3.3 多态

  • 同一个方法可以根据发送对象的不同而采用多种不同的行为方式
  • 一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(一般是父类或者是有关系的类)
import com.oop.demo06.Person;
import com.oop.demo06.Student;

public class Application {
    public static void main(String[] args) {

        //一个对象的实际类型是确定的,这里对象的类型都是Student
        //但指向的引用类型就不确定了,父类的引用指向子类
        //Student能调用的方法都是自己的或继承父类的
        Student a = new Student();
        //Person父类,可以指向子类,但不能调用子类独有的方法
        Person b = new Student();

        ((Student)b).test1();
        a.test();

    }
}
运行结果:
子类方法实现
重写的方法实现
public class Student extends Person{

    @Override
    public void test() {
        System.out.println("重写的方法实现");
    }

    public void test1(){
        System.out.println("子类方法实现");
    }
}
public class Person {
    public void test(){
        System.out.println("父类方法实现");
    }
}
  • 多态的注意事项
1. 多态是方法的多态,属性没有多态
2. 在转换类型的时候,需要有父子关系,否则会报ClassCastException的错误
3. 存在的条件:继承关系、方法需要重写、父类的引用指向子类对象
   Father a = new Son()
instanceof 类型转换

可以判断两个类之间是否存在父子关系,如果不存在关系,则编译不通过

//Student是Person的子类
public class Application {
    public static void main(String[] args) {
        //Object > Person > Student
        Object object = new Student();
        System.out.println(object instanceof Student);
        System.out.println(object instanceof Person);
        System.out.println(object instanceof Object);
        System.out.println(object instanceof String);
        Student student = new Student();
        System.out.println(student instanceof Student);
        System.out.println(student instanceof Person);
        System.out.println(student instanceof Object);
    }
}
运行结果:
true
true
true
false
true
true
true
  • 类型转换
    • 子类转换成父类,向上转型,但可能会丢失自己本来的一些方法
    • 父类转换成子类,向下转型,需要强制转换

例:Object是Student的父类,可以有Object obj = new Student;

//Student是Object的子类,Student类中有一个go方法
public class Application {
    public static void main(String[] args) {
        //类型之间的转换
        Object obj = new Student();
        //obj对象转换为Student类型,就可以使用Student类型的方法了
        ((Student)obj).go();
    }
}

6.4 抽象类

  • abstract修饰符修饰的类、方法就是抽象类和抽象方法
  • 抽象类中可以没有抽象方法,但有抽象方法一定要声明抽象类
  • 抽象类,不能用new关键字创建对象,它是用来让子类继承的
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的
  • 子类继承抽象类,必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
public abstract class Action {

    //abstract约束,其他地方实现这个方法
    public abstract void doSomething();
}
//A继承了Action抽象类,就要实现Action中没有实现的抽象方法
public class A extends Action{

    @Override
    public void doSomething() {
        
    }
}

6.5 内部类

内部类就是在一个类的内部定义一个类

  • 外部类、内部类
public class Application {
    public static void main(String[] args) {
        Outer outer = new Outer();

        Outer.Inner inner = outer.new Inner();  //通过外部类来实例化内部类
        inner.in();
        inner.getID();
        inner.getOutt();
    }
}
public class Outer {
    private int id = 1;
    private void outt(){
        System.out.println("外部类的方法");
    }

     public class Inner{
        public void in(){
            System.out.println("内部类的方法");
        }

        //获得外部类的私有属性
        public void getID(){
            System.out.println(id);
        }
        
        //获得外部类的私有方法
        public void getOutt(){
            outt();
        }
    }
}
  • 另一种内部类
public class Outer {
}

//一个java类中最多只能有一个public class,但可以有多个class
class A{
    public static void main(String[] args) {
    }
}
  • 局部内部类
public class Outer {
    public void method(){
        class Inner{				//写在方法内部的类
            public void write(){	//局部内部类也可以写方法

            }
        }
    }
}
  • 匿名内部类
public class Outer {
    public static void main(String[] args) {
        new Fruit().apple();	//实例化之后没有引用变量名
    }
}

class Fruit{
    public void apple(){
        System.out.println("苹果");
    }
}

七、Java接口的定义与实现

通过interface声明一个接口,在接口中定义方法,然后在实现类使用implements实现接口,最后在实现类中重写接口中定义的方法(方法的实现)

  • 普通类:只有具体的实现
  • 抽象类:具体实现和规范(抽象方法)都有
  • 接口:只有规范,自己无法写方法,约束和实现分离

7.1 接口的定义

  • 声明类的关键字是class,声明接口的关键字是interface,接口都需要实现类
  • 实现类中有方法的实现,接口中只有方法的定义
public interface UserService {	//使用interface声明接口
    
    //接口中的所有属性都是常量public static final
    int age = 99;
    
    //接口中定义的所有方法都是抽象的public abstract
    void add(String name);		//可以省去public abstract
    void delete(String name);
}

7.2 接口实现类的格式:

//一般接口的实现类的命名,在接口的后面加Impl
//实现类的定义:implements 接口名
//实现了接口的类,就需要重写接口中的方法
public class UserServiceImpl implements UserService{
    @Override
    public void add(String name) {
        
    }

    @Override
    public void delete(String name) {

    }
}

7.3 多个接口在同一个实现类中

  • 声明接口
public interface TimeService {
    void timer();
}
public interface UserService {
    void add(String name);
    void delete(String name);
}
  • 实现多个接口
//Java通过接口实现多继承
public class UserServiceImpl implements UserService, TimeService{
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void timer() {
        
    }
}

7.4 总结

  1. 接口有约束
  2. 接口中定义一些方法
  3. 接口不能被实例化,因为接口中没有构造方法,只是定义了方法
  4. implements可以实现多个接口
  5. 实现接口必须重写其中的方法

八、异常机制

三种异常

  • 检查性异常

用户错误或问题引起的异常,容易被程序员忽视

  • 运行时异常

这种异常容易被发现,因为写代码的人知道程序是如何运行的

  • 错误ERROR

错误不是异常,是脱离程序员控制的问题

8.1 异常体系架构

  • Java把异常当做对象来处理,并定义了一个基类java.lang.Throwable作为所有异常的超类

  • 在Java API中定义了许多异常类,分为两大类,错误ERROR和Exception

  • ERROR类对象由JVM生成并抛出,大多数错误与代码编写者所执行的操作无关

  • Exception中有一个子类RuntimeException(运行时异常)

    • ArrayIndexOutOfBoundsException 数组下标越界
    • NullPointerException 空指针异常
    • ArithmeticException 算术异常
    • MissingResourceException 丢失资源
    • ClassNotFoundException 找不到类

    这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理

    这些异常一般是写代码的时候逻辑出错

8.2 Java异常处理机制

异常处理的关键字:

try、catch、finally、rhrow、throws

public class Demo02 {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;

        //假设要捕获多个异常,异常的类型要从小到大
        try {                               //try监控区域
            System.out.println(a/b);
        }catch (Error e){                   //catch捕获想要捕获的异常类型
            System.out.println("Error");	//捕获异常后的解决方法
        }catch (Exception e){
            System.out.println("Exception");
        }catch (Throwable t){
            System.out.println("Throwable");
        }finally {                          //可以没有finally,一般用来结束IO、资源
            System.out.println("finally");
        }
    }
}
public class Demo02 {
    public static void main(String[] args) {

        try {
            new Demo02().test(10,0);
        } catch (ArithmeticException e) {
            e.printStackTrace();    //捕获异常后,在catch中解决这个异常
        }
    }

    //假设这个方法中处理不了这个异常,方法在上抛出,用throws
    //在一个地方抛出异常就好
    public void test (int a,int b) throws ArithmeticException{
        if (b==0){
            throw new ArithmeticException();    //主动抛出的异常,一般用在方法中
        }
        System.out.println(a/b);
    }
}

8.3 自定义异常

自定义异常类,继承Exception类即可

自定义异常类的步骤:

  1. 创建自定义异常类;
  2. 在方法中通过throw关键字抛出异常对象;
  3. 如果在当前抛出异常的方法中处理异常,可以使用try-catch捕获并处理;否则在方法的声明处通过throws关键字指明要抛出的给方法调用者的异常;
  4. 在出现异常方法的调用者中捕获并处理异常。

8.4 总结

  • 处理运行时异常时,采用逻辑去合理规避的同时使用try-catch辅助处理
  • 在多重catch块后,可以加一个catch(Exception)来处理可能被遗漏的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量在catch中处理异常,而不是简单的调用printStackTrace()去打印输出
  • 尽量添加finally语句块去释放占用的资源

以上内容是学习Java的一些总结笔记,后续会更新MyBatis、Spring、Spring MVC、Spring Boot等内容的学习笔记。

PS:希望通过视频学习Java的小伙伴可以去看“狂神说”的视频课程~

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值