⭐Important 学习渠道_遇见狂神说B站视频

JavaBase

注释

  1. 单行注释
//这是一个注释 
  1. 多行注释
/*
    这是个多行注释
*/
  1. 文档注释JavaDoc
/**
 *@Description Hello
 *@Author kok-s0s
 */

标识符

  • 关键字

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

  • 标识符注意点

    1. 所有的标识符都应该以字母(A-Z或者a-z),美元符($),或者下划线(_)开始
    2. 首字符之后可以是字母,美元符,下划线或数字的任何字符组合
    3. 不能使用关键字作为变量名或方法名
    4. 标识符是大小写敏感
    5. 合法标识符eg:age,$salary,_value,__1_value
    6. 非法标识符eg:123abc,-salary,#abc
        public static void main(String[] args) {
            String 王者荣耀 = "最强王者";
            System.out.println(王者荣耀);
        }
    1. 可以使用中文命名,但是一般不建议使用,也不建议使用拼音表达,因为很low

数据类型

  • 强类型语言

要求变量的使用要严格符合规定,所有变量都必须先定义后才能使用

  • 弱类型语言

与强类型相反 eg: JavaScript

基本类型(primitive type)

  • 数值类型

    • 整数类型
      1. byte 占1个字节范围
      2. int 占4个字节范围
      3. short 占2个字节范围
      4. long 占8个字节范围
    • 浮点类型
      1. float 占4个字节范围
      2. double 占8个字节范围
    • 字符类型
      • char 占2个字节范围
  • boolean类型 占1位 (true or false)

引用类型(reference type)

  • 接口
  • 数组

位(bit):是计算机内部数据存储的最小单位,11001100是一个八位二进制数。

字节(byte):是计算机中数据处理的基本单位,习惯商用大写B来表示。

1B(byte,字节)=8bit(位)

字符:是指计算机中使用的字母,数字 ,字和符号。

        //八大基本数据类型

        //整数
        int num1 = 10;
        byte num2 = 20;
        short num3 = 30;
        long num4 = 30L; //long类型要在数字后面加个L

        //小数:浮点数
        float num5 = 50.1F; //float类型要在数字后面加个F
        double num6 = 3.1415926;

        //字符
        char name = '人';
        //字符串,String不是关键字,是个类
        //String name1 = "人类";

        //布尔值:是非
        boolean flag = true;
        //boolean flag = false;

数据类型面试相关

        //整数扩展:   进制      二进制0b    十进制    八进制0     十六进制0x
        int i = 10;
        int i2 = 010; //八进制0
        int i3 = 0x10; //十六进制0x  0~9 A~F 16

        System.out.println(i);
        System.out.println(i2);
        System.out.println(i3);

        System.out.println("============================");
        //================================================
        //浮点数扩展? 银行业务怎么表示? 钱
        //BigDecimal 数学工具类
        //================================================
        //float  有限    离散   舍入误差    大约   接近但不等于
        //double

        //最好完全使用浮点数进行比较
        //最好完全使用浮点数进行比较
        //最好完全使用浮点数进行比较

        float f = 0.1f;   //0.1
        double d = 1.0 / 10;    //0.1

        System.out.println(f == d);   //false
        System.out.println(f);
        System.out.println(d);

        float d1 = 231212312312312f;
        float d2 = d1 + 1;
        System.out.println(d1 == d2);     //true


        //================================================
        //字符扩展?
        //================================================
        char c1 = 'a';
        char c2 = '中';
        System.out.println(c1);
        System.out.println((int) c1);   //强制转换
        System.out.println(c2);
        System.out.println((int) c2);   //强制转换

        //所有的字符本质还是数字
        //编码  Unicode  2个字节 可表示65536个字符   Excel  2 16 = 65536
        //Unicode 表 (97 = a  65 = A)

        //U0000 UFFFF

        char c3 = '\u0061';   //Unicode编码表示方式
        System.out.println(c3);     //a

        //转义字符
        // \t   制表符
        // \n   换行符
        System.out.println("Hello\tWorld");
        System.out.println("Hello\nWorld");


        //
        System.out.println("================================");
        String sa = new String("hello world");
        String sb = new String("hello world");
        System.out.println(sa == sb);

        String sc = "hello world";
        String sd = "hello world";
        System.out.println(sc == sd);
        //对象   从内存分析


        //布尔值扩展
        boolean flag = true;
        if(flag){
            flag=false;
        }//老手
        //Less is more 代码要精简易读

类型转换

由于java是强类型语言,所以要进行有些运算的时候的,需要用到类型转换。

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

byte,short,char->int->long->float->double

运算中,不同类型的数据需要先转化为同一类型,然后进行运算。

  • 强制类型转换

  • 自动类型转换

        int i = 128;
        byte b = (byte) i;
        System.out.println(i);
        System.out.println(b);  //内存溢出

        //强制转换  (类型)变量名  高--低
        //自动转换   低--高
        //转换的时候避免内存溢出
        /*
        注意点
        1.无法对boolean类型进行转换
        2.不能把对象类型转换为不相干的类型
        3.在把高容量转换到低容量的时候,强制转换
        4.转换的时候可能存在内存溢出,或者精度问题!
         */

        System.out.println("================");
        System.out.println((int) 23.7);  //23
        System.out.println((int) -35.89f);   //-45

        System.out.println("================");
        char c = 'a';
        int d = c + 1;
        System.out.println(d);
        System.out.println((char) d);

        //操作数比较大的时候,注意溢出问题。
        //JDK7新特性,数字之间可以用下划线分割
        int money = 10_0000_0000;
        int years = 20;
        int total = money * years;
        System.out.println(total);  //-1474836480 计算的时候会溢出
        long total2 = money * years;    //默认是int,转换之前已经存在问题了?
        System.out.println(total2);     //-1474836480
        long total3 = money * ((long) years);   //先把一个数转换为long
        System.out.println(total3);     //20000000000

        //L   l
        //都是用L表示long类型

变量

变量:既可以变化的量。

Java是一种强类型语言,每个变量都必须声明其类型。

java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。

type varName [=value] [{,varName[=value]}]
数据类型 变量名 = 值;可以使用逗号隔开来声明多个同类型变量

tips

  • 每个变量都有类型。类型可以是基本类型。也可以是引用类型。
  • 变量名必须是合法的标识符。
  • 变量声明是一条完整的语句,因此每一个声明都必须以分号结束。

变量作用域

  • 类变量
  • 实例变量
  • 局部变量
    //类变量 static
    static double salary = 2500;

    //属性:变量

    //实例变量:从属于对象;如果不自行初始化,这个类型的默认值 0 0 0
    //布尔值:默认是false
    //除了基本类型,其余的都是null
    String name1;
    int age;

    //main方法
    public static void main(String[] args) {
        //int a,b,c;
        //int a = 1, b = 2, c = 3;  //程序可读性
        String name = "kok-s0s";
        char x = 'x';
        double pi = 3.14;

        //局部变量:必须声明和初始化值
        int i = 10;
        System.out.println(i);

        //变量类型
        Demo05 demo05 = new Demo05();
        System.out.println(demo05.name1);
        System.out.println(demo05.age);

        //类变量 static
        System.out.println(salary);
    }

    //其它方法
    public void add() {

    }

常量

常量(Constant):初始化(initialize)后不能在改变值!不会变动的值。

所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。

final 常量名=值

final double PI=3.14

常量名一般使用大写字符

    //修饰符,不存在先后顺序
    static final double PI = 3.14;
    final static double height = 100;

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

变量的命名规范

  • 所有变量,方法,类型:见名知意

  • 类成员变量:首字母小写和驼峰原则:monthSalary除了第一个单词以外,后面的单词首字母大写 wrong:lastname

right:lastName

  • 局部变量:首字母小写和驼峰原则
  • 常量:大写字母和下划线:MAX_VALUE
  • 类名:首字母大写和驼峰原则:Man,GoodMan
  • 方法名:首字母小写和驼峰原则:run(),runRun

运算符

  • 算术运算符: + - * / % ++ --
  • 赋值运算符: =
  • 关系运算符: > < >= <= == != instanceof
  • 逻辑运算符: && || !
  • 位运算符: & | ^ ~ >> << >>>
  • 条件运算符: ? :
  • 扩展赋值运算符: += -= *= /=
        //++  --   自增,自减  一元运算符

        int a = 3;
        int b = a++;  //执行完这行代码后,先给b赋值,a再自增
        //a++       a = a + 1
        System.out.println(a);
        int c = ++a;  //执行完这行代码前,a先自增,再给b赋值

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);

        //幂运算 2^3   2*2*2 = 8
        double p = Math.pow(2, 3);
        System.out.println(p);
        //++  --   自增,自减  一元运算符

        int a = 3;
        int b = a++;  //执行完这行代码后,先给b赋值,a再自增
        //a++       a = a + 1
        System.out.println(a);
        int c = ++a;  //执行完这行代码前,a先自增,再给b赋值

        System.out.println(a);
        System.out.println(b);
        System.out.println(c);

        //幂运算 2^3   2*2*2 = 8
        double p = Math.pow(2, 3);
        System.out.println(p);
        /*
        A = 0011 1100
        b = 0000 1101
        -----------------------
        A&B 0000 1100
        A|B 0011 1101
        A^B 0011 0001
        ~B  1111 0010

        2*8 = 16    2*2*2*2
        <<
        >>
           0000 0000    0
           0000 0001    1
           0000 0010    2
           0000 0011    3
           0000 0100    4
           0000 1000    8
           0001 0000    16
         */
        System.out.println(2 << 3);   //16
        int a = 10;
        int b = 25;
        a += b;
        System.out.println(a);
        a -= b;
        System.out.println(a);

        //字符串连接符    +   ,String
        System.out.println("" + a + b);
        System.out.println(a + b + "");
        //x ? y : z
        //如果x==true,则结果为y,否则结果为z

        int score = 80;
        String type = score < 60 ? "不及格" : "及格";
        //if
        System.out.println(type);


        //优先级 ()

包机制

为了更好地组织类,Java提供了包机制,用于区别类名的命名空间。

包语句的语法格式为:

package pkg1[. pkg2[. pkg3...]]

一般利用公司域名倒置作为包名

为了能够使用某一个包的成员,我们需要在Java程序中明确导入该包。使用import语句可以完成此功能

import package1[.package...].(classname|*); //*为通配符

JavaDoc

javadoc命令是使用来生成自己的API帮助文档的

  • 参数信息

    • @author 作者名
    • @version 版本号
    • @since 指明需要最早使用的jdk版本
    • @param 参数名
    • @return 返回值情况
    • @throws 异常抛出情况
  • Windows下cmd命令行生成javaDoc文件操作:

eg:javadoc -encoding UTF-8 -charset UTF-8 Demo07.java

  • IDEA自动生成JavaDoc文件操作:

learn

快捷键Ctrl+\对着一个函数使用可直接生成相应的JavaDoc


Java流程控制

用户交互Scanner

java.util.Scanner是java5的新特征,能够通过Scanner类来获取用户的输入

基本语法:

Scanner s = new Scanner(System.in);

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

  • next()
    • 一定要读取到有效字符后才可以结束输入。
    • 对输入有效字符之前遇到的空白,next()方法会自动将其去掉。
    • 只有输入有效字符后才能将其后面输入的空白作为分隔符或者结束符。
    • next()不能得到带有空格的字符串。
package process_control;

import java.util.Scanner;

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

        //创建一个扫描器对象,用于接收键盘数据   用完即使关闭,因为输入输出(IO)流占用资源多
        Scanner scanner = new Scanner(System.in);
        System.out.println("使用next方式接受:");

        //判断用户有没有输入字符串
        if (scanner.hasNext()) {
            String str = scanner.next();
            System.out.println("输出的内容为:" + str);
        }

        //凡是属于IO流的类如果不关闭会一直占用资源,养成好习惯用完就关掉
        scanner.close();
    }
}
  • nextLine()
    • 以`Enter为结束符,即使用nextLine()方法返回的是输入回车之前的所有字符。
    • 可以获得空白。
package process_control;

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();
    }
}
  • 方便的写法
package process_control;

import java.util.Scanner;

public class Demo03 {
    public static void main(String[] args) {
        //从键盘接受数据
        Scanner scanner = new Scanner(System.in);

        System.out.println("请输入数据:");


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

        scanner.close();
    }
}

Scanner进阶的使用

package process_control;

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("请输入整数:");
        //if...else...
        if (scanner.hasNextInt()) {
            i = scanner.nextInt();
            System.out.println("整数数据:" + i);
        } else {
            System.out.println("输入的不是整数数据!");
        }

        System.out.println("请输入小数:");
        //if...else...
        if (scanner.hasNextFloat()) {
            f = scanner.nextFloat();
            System.out.println("小数数据:" + f);
        } else {
            System.out.println("输入的不是小数数据!");
        }
        scanner.close();
    }
}
package process_control;

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 x = scanner.nextDouble();
            m = m + 1;//m++
            sum = sum + x;//sum+=x;
            System.out.println("你输入了第" + m + "个数据,当前结果为" + sum);
        }
        System.out.println(m + "个数的和为" + sum);
        System.out.println(m + "个数的平均值是" + (sum / m));

        scanner.close();
    }
}

顺序结构

package struct;

public class ShunXuDemo {
    public static void main(String[] args) {
        System.out.println("nice");
        System.out.println("nice");
        System.out.println("nice");
        System.out.println("nice");
        System.out.println("nice");
    }
}

选择结构

  • if单选择结构
  • if双选择结构
  • if多选择结构
  • 嵌套的if结构
  • switch多选择结构

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

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

  1. byte,short,int 或者char。
  2. 从Java SE 7 开始 switch支持字符串String类型了
  3. 同时case标签必须为字符串常量和或字面量
switch(expression) {
    case value:
        //语句
        break;  //可选
    case value:
        //语句
        break;  //可选
    //你可以有任意数量的case语句
    default ://可选
        //语句
}

原文件及switch实例

package struct;

public class switchDemo {
    public static void main(String[] args) {
        String name = "kok-s0s";
        //JDK7的新特性,表达式结果可以是字符串!!!
        //字符的本质是数字

        //反编译   java---class(字节码文件)---反编译(IDEA)
        switch (name) {
            case "kok-s0s":
                System.out.println("ok!");
                break;
            case "who":
                System.out.println("who are you?");
                break;
            default:
                System.out.println("what are you going to do?");
        }
    }
}

反编译结果

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package struct;

public class switchDemo {
    public switchDemo() {
    }

    public static void main(String[] args) {
        String name = "kok-s0s";
        byte var3 = -1;
        switch(name.hashCode()) {
        case -543248720:
            if (name.equals("kok-s0s")) {
                var3 = 0;
            }
            break;
        case 117694:
            if (name.equals("who")) {
                var3 = 1;
            }
        }

        switch(var3) {
        case 0:
            System.out.println("ok!");
            break;
        case 1:
            System.out.println("who are you?");
            break;
        default:
            System.out.println("what are you going to do?");
        }

    }
}

循环结构

while

package struct;

public class whileDemo01 {
    public static void main(String[] args) {
        //输出1~100
        int i = 0;
        while (i <= 100) {
            System.out.println(i);
            i++;
        }

    }
}
package struct;

public class whileDemo02 {
    public static void main(String[] args) {
        //计算1+2+...+100=?

        int i = 0;
        int sum = 0;
        while (i <= 100) {
            sum = sum + i;
            i++;
        }
        System.out.println(sum);
    }
}

do...while

至少能执行一次循环

package struct;

public class DowhileDemo01 {
    public static void main(String[] args) {
        int i = 0;
        int sum = 0;
        do {
            sum += i;
            i++;
        } while (i <= 100);
        System.out.println(sum);
    }
}
package struct;

public class DowhileDemo02 {
    public static void main(String[] args) {
        int a = 1;
        while (a < 1) {
            System.out.println(a);
            a++;
        }
        System.out.println("===============");
        do {
            System.out.println(a);
            a++;
        } while (a < 1);

    }
}

for

package struct;

public class forDemo01 {
    public static void main(String[] args) {
        for (int i = 1; i <= 100; ++i) {
            System.out.println(i);
        }
        System.out.println("for循环结束");

    }
}
package struct;

public class forDemo02 {
    public static void main(String[] args) {
        //练习1:计算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);
    }
}
package struct;

public class forDemo03 {
    public static void main(String[] args) {
        //练习2:用while或for循环输出1-1000之间能被5整除的数,并且每行输出三个结果
        for (int i = 0; i < 1000; i++) {
            if (i % 5 == 0) {
                System.out.print(i + "\t");
            }
            if (i % (5 * 3) == 0) {
                System.out.println();
            }
        }
    }
}

九九乘法表

package struct;

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

        for (int i = 1; i <= 9; i++) {
            for (int j = 1; j <= i; j++) {
                System.out.print(i + "*" + j + "=" + (i * j) + "\t");
            }
            System.out.println();
        }
    }
}

增强for循环

java 5引入的一种主要用于数组或集合的增强型for循环

package struct;

public class forDemo05 {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 7, 5, 6};
        for (int x : numbers) {
            System.out.println(x);
        }
    }
}

break && continue

pass boring & easy

练习

package struct;

public class TestDemo01 {
    public static void main(String[] args) {
        //打印三角形  5行
        for (int i = 1; i <= 5; i++) {
            for (int i1 = 5; i1 >= i; i1--) {
                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方法详解

什么是方法?

  • Java方法是语句的集合,它们在一起执行一个功能。

    • 方法是解决一类问题的步骤的有序组合
    • 方法包含于类或对象中
    • 方法在程序中被创建,在其他地方被引用
  • 设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样便于后期的扩展。

  • Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:

    • 方法包含一个方法头和一个方法体。
      下面是一个方法的所有部分:
      • 修饰符:修饰符是一个可选项,告诉编译器如何调用该方法,定义了该方法的访问类型。
      • 返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueTypevoid
      • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
      • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型,顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
        • 形式参数:在方法被调用时用于接收外界输入的数据
        • 实参:调用方法时实际传给方法的数据
      • 方法体:方法体包含具体的语句,定义该方法的功能。
    修饰符   返回值类型 方法名(参数类型  参数名){
      ···
      方法体
      ···
      return 返回值;
    }
package method;

public class Demo01 {
    //main方法
    public static void main(String[] args) {
        //实际参数:实际调用传递给它的参数
        int sum = add(1, 2);
        System.out.println(sum);
        test();
    }

    //加法
    //形式参数,用来定义作用的
    public static int add(int a, int b) {
        return a + b;
    }

    public static void test() {
        for (int i = 1; i <= 5; i++) {
            for (int i1 = 5; i1 >= i; i1--) {
                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支持两种调用方法的方式,根据方法是否返回值来选择

当方法返回一个值的时候,方法调用通常被当作一个值。例如:

int larger = max(30,40);

如果方法返回值是void,方法调用一定是一条语句。

System.out.println("Hello,kok-s0s!");
package method;

public class Demo02 {
    public static void main(String[] args) {
        int Max = max(10, 10);
        System.out.println(Max);
    }
    //比大小
    public static int max(int a, int b) {
        int result = 0;
        if (a == b) {
            System.out.println("a==b");
            return 0;//终止大小
        } else if (a > b) {
            result = a;
        } else {
            result = b;
        }
        return result;
    }
}

方法的重载

  • 重载就是在一个类中,有相同的函数名称,但参数不同的函数
  • 方法重载的规则:
    • 方法名称必须相同。
    • 参数的列表必须不同(个数不同,或类型不同,参数排列顺序不同等)。
    • 方法的返回类型可以相同也可以不相同。
    • 仅仅返回类型不同不足以成为方法的重载。
  • 实现理论:
    • 方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,已选择对应的方法,如果匹配失败,则编译器报错。

命令行传参

  • 运行一个程序时传递信息,依靠命令行传参数给main()函数实现。

    package method;
    
    public class Demo03 {
        public static void main(String[] args) {
            //args.length 数组长度
            for (int i = 0; i < args.length; i++) {
                System.out.println("args["+i+"]:"+args[i]);
            }
        }
    }

可变参数

  • JDK1.5开始,Java支持传递同类型的可变参数给一个方法。

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

  • 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。

package method;

public class Demo04 {
    public static void main(String[] args) {
        //调用可变参数的方法
        printMax(23, 123, 412341, 54121);
        printMax(new int[]{1, 2, 3, 4, 5, 6, 7});
    }

    public static void printMax(int... numbers) {
        int Max = 0;
        for (int i = 0; i < numbers.length; i++) {
            if (Max < numbers[i])
                Max = numbers[i];
        }
        System.out.println("the max value is:" + Max);
    }
}

递归

  • 递归就是:A方法调用A方法!就是自己调用自己
  • 利用递归可以用简单的程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于有效的语句来定义对象的无限集合。
  • 递归结构包括两部分:
    • 递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
    • 递归体:什么时候需要调用自身方法。

Java数组

什么是数组

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

数组的声明和创建

  • 首先必须声明数组变量,才能在程序中使用数组。使用语法如下:

    dataType[] arrayRefVar;   //首选的方法
    或
    dataType arrayRefVar[];   //效果相同,但不是首选方法
  • Java语言使用new操作符来创建数组,语法如下:

    dataType[] arrayRefVar = new dataType[arraySize];
  • 数组的元素是通过索引访问的,数组索引从0开始。

  • arrays.length获取数组长度

package array;

public class Demo01 {
    public static void main(String[] args) {
        //变量的类型   变量的名字 = 变量的值;

        //数组类型
        int[] nums1;//定义 1.声明一个数组
//        int nums2[]; //C/C++风格
        nums1 = new int[10];    //2.创建一个数组 这里面可以存放10个int类型的数字

        int sum = 0;
        //给数组元素进行赋值
        for (int i = 0; i < nums1.length; i++) {
            nums1[i] = i + 1;
            sum += nums1[i];
        }
        for (int i = 0; i < nums1.length; i++) {
            System.out.println("nums1[" + i + "]=" + nums1[i]);
        }
        System.out.println(sum);
    }
}

三种初始化及内存分析

Java内存分析

    • 存放new的对象和数组
    • 可以被所有的线程共享,不会存放别的对象引用
    • 存放基本变量类型(会包含这个基本类型的具体数值)
    • 引用对象的变量(会存放这个引用在堆里面的具体地址)
  • 方法区
    • 可以被所有的线程共享
    • 包含了所有的class和stack变量

初始化

  • 静态初始化
int [] a = {1,2,3};
Man[] mans = {new Man(1,1),new Man(2,2)};
  • 动态初始化
int [] a = new int[2];
a[0]=1;
a[1]=2;
  • 数组的默认初始化
    • 数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方式被隐式初始化

下标越界及小结

  • 下标的合法区间:[0,length-1],如果越界就会报错;
public static void main(String[] args) {
    int[] a = new int[2];
    System.out.println(a[2]);
}
  • ArrayIndexOutOfBoundsException

  • 小结:

    • 数组是相同数据类型(数据类型可以为任意类型)的有序集合
    • 数组也是对象,数组元素相当于对象的成员变量
    • 数组长度是确定的,不可变的,如果越界,则报错:“ArrayIndexOutOfBoundsException”

数组的使用

  • 普通的For循环
  • For-Each循环
  • 数组做方法入参
  • 数组做返回值
package array;

public class Demo02 {
    public static void main(String[] args) {
        int[] arrays = {1, 2, 3, 4, 5};
        int sum = 0;
        int max = 0;
        //打印全部的数组元素
        for (int array : arrays) {
            System.out.println(array);
        }
        System.out.println("++++++++++++++");
        //计算所有元素的和
        for (int array : arrays) {
            sum += array;
        }
        System.out.println("sum=" + sum);
        System.out.println("==============");
        //查找最大的元素
        for (int array : arrays) {
            if (array > max)
                max = array;
        }
        System.out.println("max=" + max);
    }
}
package array;

public class Demo03 {
    public static void main(String[] args) {
        int[] arrays = {1, 2, 3, 4, 5};
        //JDK1.5 没有下标
        for (int array : arrays) {
            System.out.println(array);
        }
        printArray(arrays);
        System.out.println("====================");
        int[] reverse = reverse(arrays);
        printArray(reverse);
    }

    //打印数组元素
    public static void printArray(int[] arrays) {
        for (int i = 0; i < arrays.length; i++) {
            System.out.println(arrays[i] + " ");
        }
    }

    //反转数组
    public static int[] reverse(int[] arrays) {
        int[] result = new int[arrays.length];
        for (int i = 0, j = result.length - 1; i < arrays.length; i++, j--) {
            result[j] = arrays[i];
        }
        return result;
    }
}

二维数组

多维数组可以看成是数组的数组,比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。

二维数组

int a[][] = new int[2][5];

Arrays类讲解

  • 数组的工具类java.util.Arrays
  • 由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从而可以对数据对象进行一些基本的操作。
  • 查看JDK帮助文档
  • Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而“不用”使用对象来调用(注意,是“不用”而不是“不能”)
package array;

import java.util.Arrays;

public class Demo04 {
    public static void main(String[] args) {
        int[] a = {1, 2, 3, 4, 23123, 23123, 43, 24, 534};
        System.out.println(a);
        System.out.println(Arrays.toString(a));
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
        Arrays.fill(a, 2, 4, 0);
        System.out.println(Arrays.toString(a));
    }
}

冒泡排序

package array;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Demo05 {
    public static void main(String[] args) {
        int[] a = {2, 3, 4, 1, 77, 23, 5, 6};
        int[] test = sort(a);
        System.out.println(Arrays.toString(test));
    }
    //冒泡排序
    //1. 比较数组中,两个相邻的元素,如果第一个数比第二个数打,我们就交换它们的位置
    //2. 每一次比较,都会产生出一个最大,或者最小的数字
    //3. 下一轮可以少一次排序
    //4. 依次循环,知道结束!

    public static int[] sort(int[] array) {
        //外层循环,判断我们这个要走多少步
        for (int i = 0; i < array.length - 1; i++) {

            boolean flag = false;//通过flag标识位减少没有意义的比较

            //内层循环,比较判断两个数。如果第一个数,比第二个数打,则交换位置
            for (int j = 0; j < array.length - 1; j++) {
                if (array[j + 1] < array[j]) {
                    int temp = array[j + 1];
                    array[j + 1] = array[j];
                    array[j] = temp;
                    flag = true;
                }
            }
            if (flag = false) {
                break;
            }
        }
        return array;
    }
}

稀疏数组

package array;

public class Demo06 {
    public static void main(String[] args) {
        //1. 创建一个二维数组 11*11 0:没有棋子  1:黑棋  2:白棋
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;
        //输出原始的数组
        System.out.println("输出原始的数组:");

        for (int[] ints : array1) {
            for (int anInt : ints) {
                System.out.print(anInt + "\t");
            }
            System.out.println();
        }

        //转换为稀疏数组保存
        //获取有效值的个数
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (array1[i][j] != 0)
                    sum++;
            }
        }
        System.out.println("有效值的个数:" + sum);

        //2. 创建一个稀疏数组的数组
        int[][] array2 = new int[sum + 1][3];
        array2[0][0] = 11;
        array2[0][3] = 11;
        array2[0][2] = sum;

        //遍历二维数组,将非零的值。存放在稀疏数组中
        int count = 0;
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                if (array1[i][j] != 0) {
                    count++;
                    array2[count][0] = i;
                    array2[count][4] = j;
                    array2[count][2] = array1[i][j];
                }
            }
        }
        //输出稀疏数组
        System.out.println("稀疏数组");

        for (int i = 0; i < array2.length; i++) {
            System.out.println(array2[i][0] + "\t" +
                    array2[i][5] + "\t" +
                    array2[i][2] + "\t");
        }
        System.out.println("==========================");
        System.out.println("还原");
        //1. 读取稀疏数组
        int[][] array3 = new int[array2[0][0]][array2[0][6]];

        //2. 给其中的元素还原它的值
        for (int i = 1; i < array2.length; i++) {
            array3[array2[i][0]][array2[i][7]] = array2[i][2];
        }

        //3. 打印
        System.out.println("输出还原的数组");
        for (int[] ints : array1) {
            for (int anInt : ints) {
                System.out.print(anInt + "\t");
            }
            System.out.println();
        }
    }
}

面向对象编程

java的核心思想是OOP

什么是面向对象

  • 面向对象编程(Object-Oriented Programming,OOP)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据
  • 抽象
  • 三大特性:
    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。

回顾与新知

package oop;

//Demo01 类
public class Demo01 {
    //mian方法
    public static void main(String[] args) {

    }

    /*
    修饰符 返回值类型 方法吗,方法名(···){
        //方法体
        return 返回值
    }
     */
    public String sayHello() {
        return "Hello World!";
    }
}
package oop;

public class Demo02 {
    //和类一起加载的
    public static void a(){
//        b();
    }
    //类实例化 之后才存在
    public void b(){

    }
}
package oop;

public class Demo03 {
    public static void main(String[] args) {
        //实际参数和形式参数的类型要对应!

        Demo03 demo03 = new Demo03();
        int ans = demo03.add(3, 4);
        System.out.println(ans);

    }

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

//值传递
public class Demo04 {
    public static void main(String[] args) {
        int a = 1;
        System.out.println(a);
        Demo04.change(a);
        System.out.println(a);  //1
    }

    //返回值为空
    public static void change(int a) {
        a = 10;
    }
}
package oop;

//引用传递:对象,本质还是值传递
public class Demo05 {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name);

        Demo05.change(person);
        System.out.println(person.name);
    }

    public static void change(Person person) {
        //person是个对象,指向一个具体的人,可以改变属性!
        person.name = "kok-s0s";
    }
}

//定义一个Person类,有一个属性:name
class Person {
    String name;    //null
}

类与对象的创建

  • 使用new关键字创建对象
  • 使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用。
  • 类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
    • 必须和类的名字相同
    • 必须没有返回类型,也不能写void
package oop.lesson;

//学生类
public class Student {
    //属性:字段
    String name;    //null
    int age;    //0

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


public class Application {
    //一个项目应该只有一个main方法
    public static void main(String[] args) {
        //类:抽象的,实例化
        //类实例化后返回一个自己的对象
        //student对象就是一个student类的具体实例

        Student kk = new Student();
        Student gg = new Student();
        kk.name = "sdsa";
        kk.age = 19;
        System.out.println(kk.name);
        System.out.println(kk.age);
    }
}

构造器详解

package oop.lesson;

public class Person {
//    一个类即使什么都不写,它也会存在一个方法
    //现实的定义构造器

    String name;

    //实例化初始值
    //1. 使用new关键字,本质实在调用构造器
    //2. 用来初始化值
    public Person() {
        //this表示当前类
        this.name = "kok-s0s";
    }

    //有参构造,一旦定义有参构造,无参构造就必须显示定义
    public Person(String name) {
        this.name = name;
    }

    //alt+insert快捷键生成构造器

}
package oop.lesson;


public class Application {
    public static void main(String[] args) {
        //new 实例化一个对象
        Person person = new Person();

    }
}

创建对象内存分析

堆 、栈、 方法区

封装详解

  • 该露的露,该藏的藏
    • 我们程序设计要追求“高内聚,低耦合”。高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
  • 封装(数据的隐藏)
    • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
  • important :属性私有,get/set
package oop;


import oop.lesson02.Student;

public class Application {
    public static void main(String[] args) {
        Student s1 = new Student();
        s1.setName("kok-s0s");
        s1.setId(18);
        s1.setSex('b');
        System.out.println(s1.getName() + "\t" +
                s1.getId() + "\t" +
                s1.getSex());
    }
}
package oop.lesson02;

//类   私有
public class Student {
    private String name;
    private int id;
    private char sex;

    //提供一些可以操作私有属性的方法!
    //提供一些public的get,set方法
    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

什么是继承

  • 集成的本质是对某一批的抽象,从而实现对世界更好的建模。

  • extends的意思是“扩展”。子类是父类的扩展。

  • JAVA中类只有单继承,没有多继承!

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

  • 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。

  • 子类和父类之间,从意义上讲应该具有“is a”的关系。

  • object类

  • super

  • 方法重写


Super详解

super注意点:
    1. super调用父类的构造方法,必须在构造方法的第一个
    2. super 必须只能出现在子类的方法或者构造方法中!
    3. super和this不能同时调用构造方法!

Vs this:
    代表的对象不同:
        this:   本身调用者这个对象
        super:  代表父类对象的应用
    前提
        this:   没有继承也可以使用
        super:  只能在继承条件才可以使用
    构造方法
        this()  本类的构造
        super()  父类的构造
package oop.lesson03;

//在Java中,所有的类,都默认直接或者间接继承object
//Person 人:父类
public class Person {

    public Person() {
        System.out.println("Person无参构造器执行了");
    }

    protected String name = "kok-s0s";

    //私有的东西无法被继承!
    private void print() {
        System.out.println("Person");
    }

    private int money = 10_0000_0000;

    public void say() {
        System.out.println("say a word!");
    }

    public int getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }
}
package oop.lesson03;


//教师    is     人   :派生类 ,  子类
public class Teacher extends Person{

}
package oop.lesson03;

//学生   is     人   :派生类 ,  子类

//子类继承父类,就会拥有父类的全部方法!
public class Student extends Person {
    //Ctrl  +  H  打开继承树

    public Student() {
        //隐藏代码(super()):调用了父类的无参构造!
        super();//调用父类的构造器,必须要在子类构造器的第一行
        System.out.println("Student无参构造器调用了");
    }


    private String name = "man";

    public void test(String name) {
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }

    public void print() {
        System.out.println("Student");
    }

    public void test1() {
        print();    //Student
        this.print();   //Student
//        super.print();    //Person
    }
}
package oop;


import oop.lesson03.Person;
import oop.lesson03.Student;


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

//        student.test("cool");
//        student.test1();
    }
}

方法重写

重写:需要有继承关系,子类重写父类的方法!
    1. 方法名必须相同
    2. 参数列表必须相同
    3. 修饰符:范围可以扩大但不能缩小! public>Protected>Default>private
    4. 抛出的异常:范围,可以被缩小,但不能扩大:classNotException-->Exception(大)

重写,子类的方法和父类必须一致,方法体不同!

为什么需要重写:
    1. 父类的功能,子类不一定需要,或者不一定满足!
    Alt + Insert;  Override
package oop.lesson04;

//重写都是方法的重写,和属性无关
public class B {
    public void test(){
        System.out.println("B=>test()");
    }
}
package oop.lesson04;

//继承
public class A extends B{
    //Override 重写
    @Override   //注释:有功能的注释!
    public void test() {
        System.out.println("A=>test()");
    }
}
package oop;


import oop.lesson04.A;
import oop.lesson04.B;

public class Application {
    //静态方法和非静态的方法区别很大!

    public static void main(String[] args) {

        //方法的调用只和左边,定义的数据类型有关
        A a = new A();
        a.test();   //A

        //父类的引用指向了子类
        B b = new A();
        b.test();   //B

    }
}

什么是多态

/*
多态注意事项:
1. 多态是方法的多态,属性没有多态
2. 父类和子类,有联系  类型转换异常!ClassCastException!
3. 存在条件:继承关系,方法需要重写,父类引用指向子类对象!
        Father f1 = new Son();
    1. static 方法,属于类,它不属于实例
    2. final 常量
    3. private 方法
 */
package oop.lesson05;

public class Student extends Person{
    public void run(){
        System.out.println("son");
    }
}
package oop.lesson05;

public class Person {
    public void run(){
        System.out.println("run");
    }
}
package oop;


import oop.lesson05.Person;
import oop.lesson05.Student;

public class Application {
    public static void main(String[] args) {
        //一个对象的实际类型是确定的
        //new Student();
        //new Person();

        //可以指向的引用类型就不确定了;父类的引用指向子类

        //Student 能嗲用的方法都是自己的或者继承父类的!
        Student s1 = new Student();
        //Person 父类型,可以指向子类,但是不能调用子类独有的方法
        Person s2 = new Student();
        Object s3 = new Student();

        //对象能执行哪些方法,主要看对象左边的类型,和右边关系不大!
        s2.run();//子类重写了父类的方法,执行子类的放啊
        s1.run();
    }
}

instanceof和类型转换

https://www.runoob.com/java/method-instanceof.html

B站


static关键字详解

package oop.last;

//static
public class Student {

    private static int age; //静态变量      多线程!
    private double score;   //非静态变量

    public void run(){

    }

    public static void go(){

    }

    public static void main(String[] args) {
        Student s1 = new Student();
        go();
        System.out.println(Student.age);
//        System.out.println(Student.score);
        System.out.println(age);
        System.out.println(s1.score);
    }
}
package oop.last;

public class Person {

    //2 赋初始值~
    {
        //代码块(匿名代码块)
        System.out.println("匿名代码块");
    }

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

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

    public static void main(String[] args) {
        Person person = new Person();
        System.out.println("===============");
        Person person1 = new Person();
    }
}

//静态>匿名>构造
/*
静态代码块
匿名代码块
构造方法
 */
package oop.last;

//静态导入包
import static java.lang.Math.random;

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

final是断子绝孙修饰符


抽象类

package oop.again;

//abstract 抽象类 :类 extends:  单继承~        (接口可以多继承)
public abstract class Action {

    //约束~有人帮我们实现
    //abstract , 抽象方法,只有方法名字,没有方法实现
    public abstract void doSomething();

    //1. 不能new这个抽象类,只能靠子类去实现它;约束!
    //2. 抽象类中可以写普通的方法~
    //3. 抽象方法必须在抽象类中~
    //抽象的抽象:约束~


}
package oop.again;

//抽象类的所有方法,继承了它的子类,都必须要实现它的方法
public class A extends Action{
    @Override
    public void doSomething() {

    }
}

接口的定义与实现

package oop.demo;

//抽象的思维~ Java 架构师~

//interface 定义的关键字 , 接口都需要有实现类
public interface UserService {

    //常量~ public static final
    int AGE = 99;

    //接口中的所有定义其实都是抽象的 public abstract


    void add(String name);

    void delete(String name);

    void update(String name);

    void query(String name);
}
package oop.demo;

public interface TimeService {
    void timer();
}
package oop.demo;

//抽象类   extends~
//类 可以实现接口 implements 接口
//实现了接口的类,就需要重写接口中的方法~

//多继承~利用接口实现多继承~
public class UserServiceImp1 implements UserService, TimeService {
    @Override
    public void add(String name) {

    }

    @Override
    public void delete(String name) {

    }

    @Override
    public void update(String name) {

    }

    @Override
    public void query(String name) {

    }

    @Override
    public void timer() {

    }
}
作用:
    1. 约束
    2. 定义一些方法,让不同的人实现~  10---->1
    3. public abstract
    4. public static final
    5. 接口不能被实例化~,接口中没有构造方法~
    6. implements可以实现多个接口
    7. 必须要重接口中的方法~

N种内部类

https://www.bilibili.com/video/BV12J41137hu?p=76&spm_id_from=pageDriver


异常

Error和Exception

  • 异常,英文:Exception,意思是例外
  • 异常是指程序运行中出现的不期而至的各种状况,如:文件找不到,网络连接失败,非法参数等。
  • 异常发生在程序运行期间,它影响了正常的程序执行流程。

异常简单分类:

  • 检查性异常
  • 运行时异常
  • 错误ERROR

异常体系结构

  • Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。
  • 在Java API中已经定义了许多异常类,这些异常分为两大类,错误Error和异常Exception\

note


捕获和抛出异常

  • 抛出异常

  • 捕获异常

  • 异常处理五个关键词:|
    try,catch,finally,throw,throws

package exception;

public class Test {
    public static void main(String[] args) {
        try {
            new Test().test(1, 0);
        } catch (ArithmeticException e) {
            e.printStackTrace();
        }


//
//        int a = 1;
//        int b = 0;
//
//
        //假设要捕获多个异常,从小到大!

//        try {    //try监控区域
//
//            if (b == 0) {//主动抛出异常 throw throws
//                throw new ArithmeticException();//主动的抛出异常
//            }
//
//            System.out.println(a / b);
////            new Test().a();
//        } catch (Error e) { //catch(想要捕获的异常类型!) 捕获异常
//            System.out.println("Error");
//        } catch (Exception e) {
//            System.out.println("Exception");
//        } catch (Throwable t) {
//            System.out.println("Throwable");
//        } finally {  //处理善后工作
//            System.out.println("finally");
//        }

        //finally 可以不要finally 假设IO 资源,关闭!
    }

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

        System.out.println(a / b);
    }
}
package exception;

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

        //Ctrl + Alt + T
        try {
            System.out.println(a/b);
        } catch (Exception e) {
            e.printStackTrace();//打印错误的栈信息
        } finally {
            System.out.println("over");
        }
    }
}

自定义异常

用户自定义异常,只需要继承Exception类即可。

package exception;

//自定义的异常类
public class MyException extends Exception {
    //传递数字>10
    private int detail;

    public MyException(int a) {
        this.detail = a;
    }

    //toString:异常的打印信息

    @Override
    public String toString() {
        return "MyException{" + detail + "}";
    }
}
package exception;

public class Test03 {
    //可能会存在异常的方法
    static void test(int a) throws MyException {
        System.out.println("传递的参数:" + a);
        if (a > 10) {
            throw new MyException(a);//抛出
        }
        System.out.println("ok");
    }

    public static void main(String[] args) {
        try {
            test(11);
        } catch (MyException e) {
            System.out.println("MyException=>" + e);
//            e.printStackTrace();
        }
    }
}

经验总结

  • 处理运行异常时,采用逻辑去合理规避同时辅助try-catch处理
  • 在多重catch块后面,可以加一个catch(Exception)来处理可能会被遗落的异常
  • 对于不确定的代码,也可以加上try-catch,处理潜在的异常
  • 尽量去处理异常,切忌只是简单地调用printStackTrace()去打印输出
  • 具体如何处理异常,要根据不同的业务需求和异常类型去决定
  • 尽量添加finally语句块去释放占用的资源,IO~ Scanner~
Last modification:March 16, 2021
兴趣使然