博客 / 詳情

返回

Java學習筆記01 - JavaSE基礎

在線工具

java https://c.runoob.com/compile/10

在線編寫運行 Java 8 https://www.tutorialspoint.co...

SQL 在線運行 https://www.bejson.com/runcod...

Java牛客題庫 https://www.nowcoder.com/inte...

JDK, JRE, JVM

  • JDK : Java Development Kit
  • JRE : Java Runtime Enviroment
  • JVM : Java Virtual Machine

輸出Hello Wolrd

vim Hello.java
public class Hello{
    public static void main(String[] args){
        System.out.print("Hello World!");
    }
}

編譯

javac Hello.java

執行

java Hello

輸出

Hello World!

Java程序運行機制

  • 編譯型:
  • 解釋型:
  • 程序運行機制:

    源文件(*.java) => Java編譯器 => 字節碼(.class)

    => JVM ( 類裝載器 =>字節碼校驗器 => 解釋器 )

    => 操作系統平台

IDEA

新建工程

File => New => Project… => Empty Project

File => Project Structure => Project => Project SDK (1.8.0) => Project language level (8) => OK

基礎語法

1.註釋,標識符,關鍵字

註釋
//單行註釋
/* 多行註釋 */
/**
  * 文檔註釋
  * @Author itxiaoma
  */
標識符
類名,變量名,方法名都稱為標識符
  • 標識符以字母,美元($),下劃線(_)開始
  • 首字母后可以是字母,美元($),下劃線(_),數字的組合
  • 不能使用關鍵字作為變量名,方法名
  • 大小寫敏感
關鍵字(50+)

avator

2.數據類型

強類型語言:變量使用必須嚴格符合規定,所有變量都必須先定義後才能使用
Java數據類型
  1. 基本類型:(8大基本類型)

    1. 數值

      1. 整數

        1. byte:1個字節(-128~127)
        2. short:2個字節(-32768~32767)
        3. int:4個字節(-2147483648~2147483647)21億+
        4. long:8個字節(例:long num=40L;)
      2. 浮點

        1. float:4個字節(例:float num=40F;)
        2. double:8個字節
      3. 字符串char:2個字節
    2. boolean:1位,true/false
  1. 引用類型:類,接口,數組

注1:String不是數據類型,是類

注2:1bit表示1位;(bit是計算機內部數據存儲的最小單位)

​ 1Byte表示1個字節,1B=8b;

​ 1KB = 1024B;

​ 1MB = 1024KB;

​ 1GB = 1024MB;

​ 1TB = 1024GB;

Java數據類型的常見問題
  1. 整數擴展

    int a = 10;
    int b = 010;//八進制
    int c = 0x10;//十六進制
  2. 浮點型擴展

    float f = 0.1f;
    double d = 1.0/10;
    System.out.println(f==d);//false
    
    float d1 = 123123123123f;
    float d2 = d1 + 1;
    System.out.println(d1==d2);//true
    
    //float 有限 離散 舍入誤差 接近但不等於
    //不要用浮點數進行比較
    //數學工具類BigDecimal
  3. 字符類擴展

    char a = 'a';
    System.out.println((int)a);//97
    char a1 = '\u0061';
    System.out.println(a1);//a
    //所有的字符本質還是數字
    
    轉義字符:
    \t 製表符
    \n 換行
    ...

3.類型轉換

運算中,不同類型的數據會先轉換位同一類型,再進行計算

優先級:低 ==> 高

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

自動轉化:低 => 高

強制轉換: 高 => 低 (類型)變量名

注1:

  1. 不能對布爾值進行轉換
  2. 不能把對象類型轉為不相干的類型
  3. 高容量轉低容量,會有內存溢出或精度問題

注2:JDK7的新特性,數字間可以用下劃線分割(1000 = 1_000)

4.變量、常量、作用域

變量
int a = 1;
常量 - final
常量:初始化後不能改變,一般為大寫
static final double PI = 3.14;
作用域
  1. 類變量
  2. 實例變量
  3. 局部變量
public class Hello {
    //類變量:static
    static int a = 1;
    //實例變量:屬於對象,不需要初始化(會自動初始化為類型默認值)
    //布爾值默認false,除基本類型以外其他變量都是null
    String b;
    public static void main(String[] args) {
        System.out.println(a);

        int c = 3;//局部變量:必須聲明和初始化
        System.out.println(c);

        Hello obj = new Hello();
        System.out.println(obj.b);//null
    }
}
命名規則:
  1. 類變量,局部變量,方法名:駝峯(首字母小寫)
  2. 常量:大寫 + 下劃線
  3. 類型:駝峯(首字母大寫)

5.基本運算符

  1. 算術運算符:+, -, *, /, %, ++, --
  2. 賦值運算符:=
  3. 關係運算符:>, <, >=, <=, ==, !=, instanceof
  4. 邏輯運算符:&&,||,!
  5. 位運算符:&, |, ^, ~, >>, << , >>>
  6. 條件運算符:? :
  7. 擴展賦值運算符:+=, -=, *= ,/=

例:

long a = 123L;
int b = 123;
short c = 10;
byte d = 8;
System.out.println(a+d);//long
System.out.println(b+c);//int
System.out.println(c+d);//int
//結論:有long類型時轉long,否則轉int

冪運算:2^3

double pow = Math.pow(2, 3);
System.out.println(pow);//8.0

位運算

<< 乘2 
>> 除2

6.包機制

包的本質就是文件夾
  1. 包機制是為了更好地組織類,用於區別類名的命名空間
  2. 一般用公司名倒置作為報名 pakage com.baidu.www;
  3. 使用import導入包(import 包名.* 表示導入包下所有類)

7.JavaDoc生成文檔

註釋參數

/**
 * @author 作者
 * @version 版本
 * @since 需要最早使用的jdk版本
 * @param 參數
 * @return 返回值
 * @throws 異常拋出
 */

中文編碼

javadoc -encoding UTF-8 -charset UTF-8 Demo.java

流程控制

1.用户交互Scanner (Java5新特性)

基礎使用

import java.util.Scanner;

public class Demo {
    public static void main(String[] args) {
        //創建掃描器對象,用於接收鍵盤數據
        Scanner s = new Scanner(System.in);
        //判斷用户輸入
        if(s.hasNextLine()){
            String str = s.nextLine();
            System.out.println(str);
        }
        //IO流的類會一直佔用內存,用完需要關閉
        s.close();
    }
}
//next()以空格為結束符,nextLine()以回車為結束符

使用進階

計算多個數字的總和與平均數,非數字結束
Scanner s = new Scanner(System.in);
double sum = 0;
int num = 0;
while(s.hasNextDouble()){
    double x = s.nextDouble();
    sum += x;
    num++;
}
System.out.println("和是:" + sum);
System.out.println("平均值是" + (sum/num));
s.close();

2.九九乘法表

/*
1*1=1    
2*1=2    2*2=4    
3*1=3    3*2=6    3*3=9    
4*1=4    4*2=8    4*3=12    4*4=16    
5*1=5    5*2=10    5*3=15    5*4=20    5*5=25    
6*1=6    6*2=12    6*3=18    6*4=24    6*5=30    6*6=36    
7*1=7    7*2=14    7*3=21    7*4=28    7*5=35    7*6=42    7*7=49    
8*1=8    8*2=16    8*3=24    8*4=32    8*5=40    8*6=48    8*7=56    8*8=64    
9*1=9    9*2=18    9*3=27    9*4=36    9*5=45    9*6=54    9*7=63    9*8=72    9*9=81    
*/
for (int m = 1; m <= 9; m++) {
    for (int n = 1; n <= m; n++) {
        System.out.print(m + "*" + n + "=" + (m * n) + "\t");
    }
    System.out.println();
}
//System.out.print 不換行輸出

3.增強for循環(JDK1.5新特性)

int[] numbers = {1, 2, 3, 4, 5};
for (int x : numbers) {
     System.out.println(x);
}

4.label

打印101 - 150間的所有質數
outer:for (int i = 101; i <= 150; i++) {
    for (int j = 2; j < i / 2; j++) {
        if (i % j == 0) {
            continue outer;
        }
    }
    System.out.println(i);
}

Java方法

方法是用來完成特定功能的代碼片段,由方法名和方法體組成

方法名:修飾符 返回值類型 方法名 (參數類型 參數名){}

方法體:return 返回值;

參數類型:實參,形參

注:java都是值傳遞,沒有引用傳遞

1.方法的重載

重載就是在一個類中,有相同的函數名稱,但形參不同的函數

方法重載規則:

  1. 方法名稱必須相同
  2. 參數列表必須不同(個數,類型,參數順序不同)
  3. 返回類型可相同可不同

2.命令行傳參

程序運行時傳遞參數,可以通過main方法傳遞
public static void main(String[] args) {
    for (int i = 0; i < args.length; i++) {
        System.out.println(args[i]);
    }
}

3.可變參數(JDK1.5新特性)

public static void main(String[] args) {
    test(1,2,3);
}
public static void test(int... i){
    System.out.println(i[0]);
    System.out.println(i[1]);
    System.out.println(i[2]);
}

4.遞歸

遞歸頭:什麼時候不調用自身方法。如果沒有頭,將陷入死循環。

遞歸體:什麼時候需要調用自身方法。

Java數組

數組是相同類型數據的有序集合
dataType[] arrayRefVar = new dataType[size];

int nums[] = new int[10];
//二維數組
int[][] n = new int[2][2];
int[][] n = {{1,2},{3,4}} 

基本特點

  1. 長度是確定的,一旦創建,長度不可變
  2. 元素類型必須相同
  3. 數組對象本身在堆中(數組是引用類型,可看做對象,數組元素相當於對象的成員變量,Java的對象在堆中)

內存分析

graph LR
A(java內存)
A --> B(堆)
      B -->B1[存放new的對象和數組]
      B -->B2[可以被所有線程共享,不會存放別的對象引用] 
A --> C(棧)
      C -->C1[存放基本變量類型,包含具體數值]
      C -->C2[引用對象的變量,存放引用在堆中的地址] 
A --> D(方法區)
      D -->D1[可以被所有線程共享]
      D -->D2[包含所有calss和static變量] 
//1.聲明數組
int[] nums;//在棧中
//2.創建數組
nums = new int[10];//在堆中

三種初始化狀態

//靜態初始化
int[] a = {1, 2, 3};
Man[] mans = {new Man(1),new Man(2)}

//動態初始化(包含默認初始化)
int[] b = new int[10];//默認分配10個0
b[0] = 10;

注:數組是引用類型,數組元素相當於類的實例變量,數組創建時分配空間,數組元素也會按默認值初始化。

數組工具類java.util.Arrays

打印數組元素 Arrays.toString(a);
數組填充 Arrays.fill(a, 0 , 1, 0); 數組下標0-1的元素用0填充
數組排序 Arrays.sort(a);
比較數組 equals
查找數組元素 binarySearch 對排序好的數組進行二分法查找

冒泡排序

  1. 共有八大排序
  2. 時間複雜度為O(n2)

稀疏數組

當一個數組中大部分元素為0或值相同時,可以使用稀疏數組保存

處理方式:

1.記錄數組行列數,不同值數

2.把不同值的元素行列信息,元素值記錄在小規模數組中

/*
稀疏數組
1    2    1
2    3    2
還原數組
0    0    0    0    0    0    0    0    0    0    0    
0    0    1    0    0    0    0    0    0    0    0    
0    0    0    2    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
0    0    0    0    0    0    0    0    0    0    0    
*/
public class Demo {
    public static void main(String[] args) {
        int[][] array1 = new int[11][11];
        array1[1][2] = 1;
        array1[2][3] = 2;
        int sum = 0;
        for (int i = 0; i < 11; i++) {
            for (int j = 0; j < 11; j++) {
                if (array1[i][j] != 0) {
                    sum++;
                }
            }
        }
        int[][] array2 = new int[sum + 1][3];
        array2[0][0] = 11;
        array2[0][1] = 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][1] = j;
                    array2[count][2] = array1[i][j];
                }
            }
        }
        System.out.println("稀疏數組");
        for (int j = 1; j < array2.length; j++) {
            System.out.println(array2[j][0] + "\t" + array2[j][1] + "\t" + array2[j][2]);
        }
        System.out.println("還原數組");
        int[][] array3 = new int[array2[0][0]][array2[0][1]];
        for (int j = 1; j < array2.length; j++) {
            array3[array2[j][0]][array2[j][1]] = array2[j][2];
        }
        for (int[] ints : array3) {
            for (int num : ints) {
                System.out.print(num + "\t");
            }
            System.out.println();
        }
    }
}

面向對象

以類的方式組織代碼。以對象組織(封裝)數據

三大特性:封裝,繼承,多態

1.創建類與對象

一個項目應該只存在一個main方法
創建對象
使用new創建對象時,除了分配內存空間,還會給創建好的對象進行默認初始化,及調用類中的構造器。

com/oop/demo/Application.java

package com.oop.demo;
public class Application {
    public static void main(String[] args) {
        //類:抽象的,實例化後會返回一個自己的對象
        Student xiaoming = new Student();
        Student xiaohong = new Student();
        xiaoming.name = "小明";
        xiaoming.age = 20;
        xiaohong.name = "小紅";
        xiaohong.age = 21;
        System.out.println("姓名:" + xiaoming.name + "\t年齡:" + xiaoming.age);
        xiaoming.study();
        System.out.println("姓名:" + xiaohong.name + "\t年齡:" + xiaohong.age);
        xiaohong.study();
    }
}

com/oop/demo/Student.java

package com.oop.demo;
public class Student {
    //屬性
    String name;
    int age;
    //方法
    public void study() {
        System.out.println(this.name + "在學習");
    }
}
構造器(構造方法)
  1. 必須和類名相同
  2. 必須沒有返回類型(不能寫void)
  3. 一旦定義了有參數的構造器,new對象時想不傳參數,就必須寫一個無參數構造器
public class Student {
    //屬性
    String name;
    int age;
    //無參(默認)構造器
    public Student(){
        
    }
    //有參
    public Student(String name){
        this.name = name;
    }
    public Student(String name,int age){
        this.name = name;
        this.age = age;
    } 
}

創建對象內存分析

public class Application {
    public static void main(String[] args) {
        //類:抽象的,實例化後會返回一個自己的對象
        Student xiaoming = new Student();
        Student xiaohong = new Student();
        xiaoming.name = "小明";
        xiaoming.age = 20;
        xiaohong.name = "小紅";
        xiaohong.age = 21;
        System.out.println("姓名:" + xiaoming.name + "\t年齡:" + xiaoming.age);
        xiaoming.study();
        System.out.println("姓名:" + xiaohong.name + "\t年齡:" + xiaohong.age);
        xiaohong.study();
    }
}

方法區也在堆中;

靜態方法區和類一起加載,所以靜態方法可以直接調用,不需要實例化

  1. 加載Application和Student類信息到方法區
  2. 加載main()方法到棧中
  3. 加載xiaoming和xiaohong引用變量名到棧中
  4. 加載Student xiaoming = new Student();和Student xiaohong = new Student();實例到堆中
  5. xiaoming和xiaohong調用方法區的study方法

注:基本類型外的變量都是引用類型,是通過引用來操作的;引用名在棧中,指向對象實體在堆中的地址。

封裝

禁止直接訪問一個對象中數據的實際表示,應通過接口操作來訪問。

屬性私有(private),get/set

public class Student {
    private String name;
    private int age;
    public String getName() {
        return this.name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getAge() {
        return age;
    }
}

繼承extends

繼承的本質是對某一批類的抽象,從而實現更好的建模;

繼承是類之間的關係,子類繼承(extends)父類的全部public方法;

私有的屬性和方法無法被繼承

注:

  1. Java中只有單繼承,沒有多繼承 (一個子類只能有一個父類)
  2. Java中所有類,都默認直接或間接繼承Object類

Super

注意點
  1. super調用父類的構造方法,必須在構造方法的第一行
  2. super只能出現在子類的方法或構造方法中
  3. super和this不能同時在構造方法中調用(都需要在第一行)
super和this的區別
this super
代表對象不同 調用者本身的對象 父類對象的引用
使用前提不同 沒有繼承也能使用 只能在有繼承時使用
調用構造方法不同 調用本類的構造方法 調用父類的構造方法

com/oop/demo/Application.java

package com.oop.demo;

public class Application {
    public static void main(String[] args) {
        Student xiaoming = new Student();
        xiaoming.test1();
        //Person無參構造
        //Student無參構造
        //Student
        //Student
        //Person
    }
}

com/oop/demo/Person.java

package com.oop.demo;

public class Person {
    public Person() {
        System.out.println("Person無參構造");
    }
    public void print(){
        System.out.println("Person");
    }
}

com/oop/demo/Student.java

package com.oop.demo;

public class Student extends Person{
    public Student() {
        //隱藏代碼:調用了父類的無參構造super();
        //super();
        System.out.println("Student無參構造");
    }
    public void print(){
        System.out.println("Student");
    }
    public void test1(){
        print();
        this.print();
        super.print();
    }
}

方法重寫@Override

子類的方法和父類必須要一致,方法體不同

重寫都是方法的重寫,和屬性無關

靜態方法不能被重寫 !

注意點
  1. 方法名,參數列表必須相同
  2. 修飾符範圍可以擴大不能縮小
  3. 拋出異常範圍可以縮小不能擴大
代碼示例

靜態方法

public class B {
    public static void test(){
        System.out.println("B=>test()");
    }
}
public class A extends B{
    public static void test(){
        System.out.println("A=>test()");
    }
}
public class Application {
    public static void main(String[] args) {
        //靜態方法:方法調用只和左邊定義的數據類型有關
        A a = new A();
        a.test();//A=>test()
        //父類的引用指向了子類
        B b = new A();
        b.test();//B=>test()
    }
}

方法重寫

public class B {
    public void test(){
        System.out.println("B=>test()");
    }
}
public class A extends B{
    @Override
    public void test() {
        System.out.println("A=>test()");
    }
}
public class Application {
    public static void main(String[] args) {
        A a = new A();
        a.test();//A=>test()
        B b = new A();
        b.test();//A=>test()
    }
}

多態

同一方法根據發送對象不同,採用多種不同的行為方式;

一個對象的類型是確定的,但可以指向對象的引用類型有很多(可以是子類,父類,Object)

多態存在的條件:

  1. 有繼承關係
  2. 子類重寫父類方法
  3. 父類引用指向子類對象

注:多態是方法的多態,屬性沒有多態。

無法重寫的方法
  1. static方法,屬於類,不屬於實例
  2. final 常量 (final修飾的類不能被繼承)
  3. private方法
//子類能調用的方法都是自己的或繼承父類的
A a = new A();
B b = new B();
//對象能執行哪些方法看左邊的引用類型
//父類引用可以指向子類,但不能調用子類獨有的方法
B c = new A();
a.test();//A=>test()
b.test();//B=>test()
//子類重寫了父類方法,會執行子類的方法
c.test();//A=>test()

instanceof和類型轉化

  1. 父類引用可以指向子類的對象,反過來不行
  2. 子類轉換為父類稱為向上轉型,可能丟失自己本來的一些方法
  3. 父類轉換為子類稱為向下轉型,需要強制轉換
public class Application {
    public static void main(String[] args) {
        //子類特有方法go
        Student s = new Student();
        s.go();
        //向上轉型,轉型後無法再調用go方法
        Person p = s;
        //向下轉型
        ((Student) p).go();
    }
}

static關鍵字

靜態變量
private static int age;
靜態方法
public class Application {
    private static void test(){
        System.out.println("Static Function");
    }
    public static void main(String[] args) {
        test();
    }
}
靜態代碼塊
public class Person {
    {
        System.out.println("匿名代碼塊");
    }
    static {
        System.out.println("靜態代碼塊");//只會在類加載時執行一次
    }
    public Person() {
        System.out.println("構造方法");
    }
    public static void main(String[] args) {
        Person p = new Person();
        //靜態代碼塊
        //匿名代碼塊
        //構造方法
    }
}
靜態導入包
import static java.lang.Math.random;
public class Person {
    public static void main(String[] args) {
        System.out.println(random());
    }
}

抽象類 abstract

//抽象類 (接口可以多繼承)
abstract class Person {
    public abstract void doSomething();//抽象方法:只有方法名,沒有方法體
}

注:

  1. 抽象類不能new,只能靠子類實現
  2. 抽象方法必須在抽象類中,但抽象類可以包含普通方法

接口 interface

對對象的抽象,約束和實現分離:面向接口編程

注:

  1. 接口不能被實例化,接口中沒有構造方法
  2. 接口中所有方法都是抽象的(public abstract)
  3. 接口中只有常量(public static final)
  4. 類通過implements實現接口,一個類可以實現多個接口,實現多繼承
  5. 實現接口的類,必須重寫接口中所有方法
public interface UserService {
    void userTest1();
    void userTest2();
}
public interface TimeService {
    void time1();
    void time2();
}
public class UserTime implements UserService,TimeService{
    @Override
    public void userTest1() {
    }
    @Override
    public void userTest2() {
    }
    @Override
    public void time1() {
    }
    @Override
    public void time2() {
    }
}

內部類

匿名對象:不將實例保存到變量(棧)中,只在堆內存中使用對象

public class Application {
    public static void main(String[] args) {
        new Apple().eat();
    }
}
class Apple{
    public void eat(){
        System.out.println("吃蘋果");
    }
}

匿名內部類

public interface UserService {
    void userTest1();
    void userTest2();
}
public class Application {
    UserService u = new UserService() {
        @Override
        public void userTest1() {
        }
        @Override
        public void userTest2() {
        }
    };
}

異常Error Exception

Error

Error類對象由JVM生成並拋出,大多數錯誤與操作無關,發生錯誤時JVM一般會終止線程;

如內存溢出(OutOfMemeryError),棧溢出,類定義錯誤(NoClassDefFoundError),鏈接錯誤(LinkageError)

Exception

異常通常由邏輯錯誤引起,應儘量避免
  1. 非運行時異常(IO異常...)
  2. 運行時異常(RuntimeException)

注:Error通常是致命性錯誤,程序無法處理;Exception通常可以且應該儘可能的處理。

異常處理機制

  1. try 監控區域 (必要)
  2. catch 捕獲異常 (必要)
  3. finally 最終處理 (釋放佔用資源)
  4. throw 拋出異常(一般在方法中使用 )
  5. throws

注:捕獲多個異常需要從小到大XXXException < XXXException < Throwable

public class Application {
    public static void main(String[] args) {
        int a = 1;
        int b = 0;
        try{
            if(b == 0){
                throw new ArithmeticException();
            }
            System.out.println(a/b);
        }catch (ArithmeticException e){
            e.printStackTrace();//打印錯誤的棧信息
        }catch (Exception e){
            
        }catch (Throwable e){
            
        }finally {
            
        }
    }
}

自定義異常

用户自定義異常類,只需要繼承Exception類即可
public class MyException extends Exception {
    String msg;

    public MyException(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "MyException{" + msg + "}";
    }
}
public class Application {
    static void test(String msg) throws MyException{
        throw new MyException(msg);
    }
    public static void main(String[] args) {
        try{
            test("test");
        }catch (MyException e){
            System.out.println(e);//MyException{test}
        }
    }
}
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.