基本概念

本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2022-07-07

基础

JDK JRE JVM

JDK = JRE + Java开发工具(javac, java, javadoc)

JRE = JVM + Java核心类库

使用javadoc生成文档

javadoc -d docDirName -author -version demo01.java

.java文件

在一个java源文件中可以声明多个class,但是只能有一个类声明为public,且这个类的类名需要与该.java文件名一致

程序的入口是main()方法,除入参外,格式是固定的。

public class Hello {
  public static void main(string[] args) {
    // ...
  }
}

public是装饰符 static是声明为静态方法 void说明main是没有返回值的

数据类型

基本数据类型:整数型(byte/short/int/long)、浮点型(float/double)、字符(char)、布尔型(boolean)

引用数据类型:类(class)、接口(interface)、数组([] array)

字符串是一个类类型。

整数型

byte: 1字节 = 8bit,表数范围(-128, 127)

short: 2字节 (-2^15, 2^15-1)

int: 4字节 (-2^31, 2^31-1)

long: 8字节 (-2^63, 2^63-1)

声明long类型的变量必须以lL结尾。

浮点型

单精度float:4字节 表数范围(-3.403E38,3.403E38)

双精度double: 8字节 表数范围(-1.798E308, 1.798E308)

单精度可以精确到7位有效数字,很多情况下,精度很难满足需求,double是双精度,精度是float的两倍,通常采用此类型, Java中的浮点型常量默认为double型,声明float变量,后面需要以fF结尾。

字符型

char: 2字节,使用单引号定义,只能有一个字符

char c = '中';

// 转义字符 换行符
char c2 = '\n';

// 制表符
char c3 = '\t';

// unicode
char c4 = '\u0043'

布尔型

boolean flag = true;

基本数据类型之间的运算

自动类型提升

当容量小的数据类型的变量与容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型,此时的容量大小指的是,表示数的范围的大和小。比如 float容量要大于long的容量

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

byte b1 = 2;
int i1 = 2;

int i2 = b1 + i1;
// 字节小的和字节大的类型做运算,应该使用字符大的类型去接收结果。

float f = b1 + i1; // 这样也可以,但是会变成浮点型 f为 4.0

char c1 = 'a';
int i2 = 10;
int r = c1 + i2; // 107, 字符串以Unicode码对应的数字与整数型进行运算

// 当byte、char、short三种类型的变量作运算时,结果为int类型
char c2 = 'b'
short s = 11;
int r1 = c2 + s;

byte b2 = 12;
byte b3 = 13;
int r2 = b2 + b3; // 即使是byte同种类型作运算,结果为int型

强制类型转换

double d1 = 12.9;
int i1 = (int)d1; // 强转,会损失精度 i1的结果是12


int i2 = 128;
byte b = (byte)i2; // b会是-128

强制类型可能为出现精度损失。

long l = 123123; // 没加l为默认当做int类型

byte b = 12;
byte b1 = b + 1; // error 整数型常量1的默认类型是int型
int i = b + 1;

字符串类型

String属于引用数据类型。


String s1 = "hello wrold";

char h = s1.charAt(0); // 获取s1下标为0的字符

String s2 = "a";

String s3 = ""; 

char c = ''; // char类型不能是空字符

String info = s1 + s2; // 字符串用+ 是连接运算

boolean b = true;
String r = s2 + b; // atrue String类型

String 可以和8种基本数据类型做运算,且运算只能是连接运算,结果仍然是String类型。

运算符

逻辑运算符

逻辑运算符&|!^操作的都是boolean类型的变量。

短路运算符 &&|| 与逻辑运算符 &| 的区别是:

// & 与 && 的运算结果相同
// 当符号左边是true时,二者都会执行符号右边的运算
// 当符号左边是false时,&继续执行符号右边的运算,而&&不再执行符号右边的运算

boolean b1 = false;
int num1 = 10;
if (b1 & (num1++ > 0)) {
  System.out.println("1");
} else {
  System.out.println("2");
}
System.out.println(num1); // 11

boolean b2 = false;
int num2 = 10;
if (b2 && (num2++ > 0)) {
  System.out.println("1");
} else {
  System.out.println("2");
}
System.out.println(num2); // 10

位运算符

&|~(取反)、^,如果操作的都是数字类型,就是位运算符,最终操作的是它们的二进制数的运算,结果也是数字。

对应的还有

>>(右移):在一定范围里,每向右移N位相当于除以一个2的n次方,最高位的补位根据之前的符号位进行是0补0,是1补1。

<<(左移):在一定范围例,每向右移N位相当于乘以一个2的n次方,因为正数可能会移成一个负数。后面一律补0。

>>>(无符号右移)

<<<(无符号左移)

使用Scanner获取键盘输入

// 1.导包
import java.util.Scanner;

public class demo01 {
  public static void main(String[] args) {
    // 2.实例化 Scanner 对象
    Scanner scan = new Scanner(System.in);

    System.out.print("输入一个数字:");

    // 3.调用nextInt()接收键盘输入的数字
    int num = scan.nextInt();

    System.out.println("你输入的数字是: " + num);

    // Scanner.next() 接收字符串输入
    // Scanner.nextDouble() 接收浮点型输入
    // Scanner.nextBoolean() 接收布尔型输入

    // 当输入的类型与要求的类型不匹配时,会报异常。
  }
}

控制语句

// 求100以内的质数
public class demo02 {
  public static void main(String[] args) {
    // 获取当前时间的毫秒数
    long start = System.currentTimeMillis();

    for (int i = 2; i <= 100; i++) {
      boolean flag = true;
      // 取开方就可以
      // 因为 比如非质数36 它的因数 2 * 18 / 3 * 12 / 4 * 9 / 6 * 6 / 9 * 4 / ...
      // 能够被除开的是一对一对的,所以检查前半部分就够了 是否被2,3,4,6除尽 这个6就是开方而来
      // 这一对一对就以其开方作为中间线,中间线之后的就是前面的调换乘数位置而已 所以只检查前半部分即可
      for (int j = 2; j <= Math.sqrt(i); j++) {
        if (i % j == 0) {
          flag = false;
          break;
        }
      }
      if (flag == true) {
        System.out.println(i);
      }
    }

    long end = System.currentTimeMillis();
    System.out.println("所花费的时间为: " + (end - start) + " ms");
  }
}

跳出循环结构

public class demo03 {
  public static void main(String[] args) {
    for (int i = 1; i <= 4; i++) {
      for (int j = 1; j <= 10; j++) {
        if (j % 4 == 0) {
          break;
        }
        System.out.print(j); // 输出123 输出4遍 break默认跳出距离此关键字最近的一层循环结构
      }
      System.out.println();
    }

    System.out.println("跳转指定的循环结构");

    label:for (int m = 1; m <= 4; m++) {
      for (int n = 1; n <= 10; n++) {
        if (n % 4 == 0) {
          break label; // 结束指定标识的一层循环结构
        }
        System.out.print(n); // 输出123 输出1遍
      }
      System.out.println();
    }
  }
}

continue 也是一样,可以结束指定标识的一层循环结构的当次循环

一个交互小程序

demo04FamilyAccount.java

public class demo04FamilyAccount {
  public static void main(String[] args) {
    boolean isFlag = true;

    String details = ""; // 记录用户的收入和支出的详情

    int balance = 10000; // 初始金额


    while (isFlag) {
      System.out.println("---------------------家庭收支记账软件---------------------");
      System.out.println("                       1 收支明细                       ");
      System.out.println("                       2 登记收入                       ");
      System.out.println("                       3 登记支出                       ");
      System.out.println("                       4 退   出\n                     ");
      System.out.print("                       请选择(1-4): ");


      // 获取用户的选择
      char selection = demo04Utility.readMenuSelection();

      switch (selection) {
        case '1':
          System.out.println("---------------------当前收支明细记录---------------------");
          System.out.println("收支\t\t账户金额\t\t收支金额\t\t说  明\n");
          System.out.print(details);
          System.out.println("-------------------------------------------------------");
          break;
        case '2':
          System.out.print("本次收入金额:");
          int money = demo04Utility.readNumber();
          System.out.print("本次收入说明:");
          String info = demo04Utility.readString();
          balance += money;
          details += "收入\t\t" + balance + "\t\t" + money + "\t\t\t" + info + "\n";
          System.out.println("------------------------登记完成------------------------");
          break;
        case '3':
          System.out.print("本次支出金额:");
          int money2 = demo04Utility.readNumber();
          System.out.print("本次支出说明:");
          String info2 = demo04Utility.readString();

          if (balance >= money2) {
            balance -= money2;
            details += "支出\t\t" + balance + "\t\t" + money2 + "\t\t\t" + info2 + "\n";
          } else {
            System.out.println("支出超出账户额度,支付失败");
          }
          System.out.println("------------------------登记完成------------------------");
          break;
        case '4':
          System.out.print("确认是否退出(Y/N): ");
          char isExit = demo04Utility.readConfirmSelection();

          if (isExit == 'Y') {
            isFlag = false; // 改变变量,结束循环,程序结束
          }
          break;
      }
    }
  }
}

demo04Utility.java

import java.util.Scanner;

public class demo04Utility {

  private static final Scanner scanner = new Scanner(System.in);

  /**
   * 用于界面菜单的选择 该方法读取键盘,如果用户键入1-4中的任意字符,则方法返回
   * @return 返回为用户键入的字符
   */
  public static char readMenuSelection() {
    char c;
    // 使用一个"死"循环 是因为用户可能会有无数次输入都不符合预期,不符合预期就重新开始 直到用户输入期望值
    for (;;) {
      String str = readKeyBoard(1);
      c = str.charAt(0);
      if (c != '1' && c != '2' && c != '3' && c != '4') {
        System.out.print("选择错误,请重新输入:");
      } else {
        break;
      }
    }
    return c;
  }

  /**
   * 用于收入和支出金额的输入 该方法读取键盘 该方法从键盘读取一个不超过4位长度的整数
   * @return 返回用户输入的数字
   */
  public static int readNumber() {
    int n;
    for (;;) {
      String str = readKeyBoard(4);
      try {
        n = Integer.parseInt(str);
        break;
      } catch (NumberFormatException e) {
        System.out.print("数字输入错误, 请重新输入:");
      }
    }
    return n;
  }

  /**
   * 用于收入和支出说明的输入 从键盘读取一个不超过8位长度的字符串
   * @return 返回用户输入的相关收入和支出的说明
   */
  public static String readString() {
    return readKeyBoard(8);
  }

  /**
   * 用于确认选择的输入,该方法从键盘读取Y或N,并将其作为返回值
   * @return Y/N
   */
  public static char readConfirmSelection() {
    char c;
    for (;;) {
      String str = readKeyBoard(1).toUpperCase();
      c = str.charAt(0);
      if (c == 'Y' || c == 'N') {
        break;
      } else {
        System.out.print("选择错误,请重新输入:");
      }
    }
    return c;
  }

  /**
   * 封装读取键盘输入方法,当输入不满足期望时可重新输入 while(scanner.hasNext())
   * @param limit 对输入长度的限制
   * @return 输入的信息
   */
  private static String readKeyBoard(int limit) {
    String line = "";

    while (scanner.hasNext()) {
      line = scanner.nextLine();
      int lineLen = line.length();
      if (lineLen < 1 || lineLen > limit) {
        System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
        continue;
      }
      break;
    }

    return line;
  }
}

数组

public class ArrayTest {
  public static void main(String[] args) {
    // 1. 初始化
    // 静态初始化 数组初始化和数组元素的赋值操作同时进行
    int[] ids = new int[]{1001, 1002, 1003, 1004};
    // 可以类型推断
    int[] ids2 = {3, 4, 5, 6};

    // 动态初始化 数组初始化和数组元素的赋值操作分开进行
    String[] names = new String[5];

    // 数组一旦初始化完成,其长度就确定了

    // 2. 调用数组指定位置的元素
    names[0] = "Anna";
    names[1] = "Bob";

    // 3. 获取数组的长度 需要注意的是,String获取长度是length()方法,而数组获取长度的是length属性
    System.out.println(names.length);

    // 4. 如何遍历数组
    for(int i = 0; i < names.length; i++) {
      System.out.println(names[i]); // 未赋值的默认是null
    }

    // 4.1 简写
    for (String name : names) {
      System.out.println(name);
    }

    char[] arr = new char[4];
    for(int i = 0; i < arr.length; i++) {
      if (arr[i] == 0) {
        // tips
        System.out.println("char数组的默认值与0是相等的");
      }
    }

    long[] bArr = new long[2];
    System.out.println(bArr[0]);
  }
}

// 数组元素的未初始化的默认值
// 基本数据类型
//  - int/short/long/byte数组:默认为0
//  - float/double数组:默认为0.0
//  - char数组:默认为ASCII码为0(即'\u0000')的值 => NUL 字符是空
//  - boolean数组:默认为false
// 引用数据类型
//  - String:默认为null

二维数组

public class ArrayTest2 {
  public static void main(String[] args) {
    int [][] arr = new int[][]{{1, 2}, {3, 4}, {5, 6}};

    String [][] strArr = new String[3][2];
    String [][] strArr2 = new String[3][];

    int[] arr2[] = new int[3][2];
    // 等同于 int[][] arr2 = new int[3, 2]
    // 一维数组也可以这样声明
    String names[] = new String[3];

    int[][] arr3 = new int[4][3];
    System.out.println(arr3[0]); // [I@3af49f1c  地址
    System.out.println(arr3[0][0]); // 0

    float[][] arr4 = new float[4][3];
    System.out.println(arr4[0]); // [F@19469ea2
    System.out.println(arr4[0][0]); // 0.0


    double[][] arr5 = new double[4][]; // 二维数组初始化时只指定外层的个数,说明创建了一个数组arr5包含4个空数组
    System.out.println(arr5[0]); // null
  }
}

杨辉三角

public class YangHuiTest {
  public static void main(String[] args) {
    int[][] arr = new int[10][];
    for (int i = 0; i < arr.length; i++) {
      arr[i] = new int[i+1];
      for (int j = 0; j < arr[i].length; j++) {
        if (j == 0 || (j == arr[i].length - 1)) {
          arr[i][j] = 1;
        } else {
          arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
        }
        System.out.print(arr[i][j] + " ");
      }
      System.out.println();
    }
  }
}

输出回形文

public class HuiXingTest {
  public static void main(String[] args) {
    int[][] arr = new int[9][8];
    String direction = "right";
    int i = 0;
    int j = 0;
    int maxI = arr.length - 1;
    int maxJ = arr[0].length - 1;
    label:for (; i < arr.length; ) {
      for (; j < arr[i].length; ) {
        if (i == 0 && j == 0) {
          arr[i][j] = 1;
          j++;
          continue;
        }

        switch (direction) {
          case "right":
            arr[i][j] = arr[i][j-1]+1;
            break;
          case "down":
            arr[i][j] = arr[i-1][j]+1;
            break;
          case "left":
            arr[i][j] = arr[i][j+1]+1;
            break;
          case "up":
            arr[i][j] = arr[i+1][j]+1;
            break;
        }

        if (arr[i][j] == ((maxI + 1) * (maxJ + 1))) {
          break label;
        }

        if (direction == "right" && j == maxJ - i) {
          direction = "down";
        }

        if (direction == "down" && i == maxI - (maxJ - j)) {
          direction = "left";
        }

        if (direction == "left" && j == maxI - i) {
          direction = "up";
        }

        if (direction == "up" && i == j + 1) {
          direction = "right";
        }

        switch (direction) {
          case "right":
            j++;
            break;
          case "down":
            i++;
            break;
          case "left":
            j--;
            break;
          case "up":
            i--;
            break;
        }
      }
    }

    for (int k = 0; k < arr.length; k++) {
      for (int m = 0; m < arr[k].length; m++) {
        int num = arr[k][m];
        if (num < 10) {
          System.out.print("0" + arr[k][m] + " ");
        } else {
          System.out.print(arr[k][m] + " ");
        }
      }
      System.out.println();
    }
  }
}

Arrays工具类

常用工具函数

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

    int[] arr1 = new int[]{1, 2, 3, 4};
    int[] arr2 = new int[]{2, 1, 3, 4};
    // 1. Arrays.equals() 判断两个数组是否相等
    boolean b1 = Arrays.equals(arr1, arr2);
    System.out.println(b1); // false


    // 2. Arrays.toString() 输出数组信息
    String s1 = Arrays.toString(arr1);
    System.out.println(s1); // "[1, 2, 3, 4]"

    // 3. Arrays.fill(int[] a, int val) 将指定的值填充到数组之中
    int[] arr3 = new int[4];
    Arrays.fill(arr3, 1);
    System.out.println(Arrays.toString(arr3)); // "[1, 1, 1, 1]"

    // 4. Arrays.sort() 对数组进行排序
    int[] arr4 = new int[]{1, 3, 2, 4, 5};
    Arrays.sort(arr4);
    System.out.println(Arrays.toString(arr4)); // "[1, 2, 3, 4, 5]"

    // 5. Arrays.binarySearch 对数组进行二分查找,需要数组是有序的。
    int[] arr5 = new int[]{11, 22, 33, 45, 66, 78, 99};
    int index = Arrays.binarySearch(arr5, 99);
    System.out.println(index); // 6 如果返回的是一个负数就是未找到,具体是负多少不确定
  }
}