大數據開發成長之路——Java基礎(一)

Java基礎

這裏主要介紹學習大數據過程中的Java基礎知識,歡迎大家共同交流。

環境

  • Java的運行環境和機制如圖所示
    在這裏插入圖片描述
  • JRE(Java Runtime Environment) Java運行時環境
  • JDK(Java Development Kit) Java開發工具包
    需要在電腦上安裝Java SE,下載地址,我的電腦是Windows系統,安裝後將bin目錄放入系統環境變量,使用cmd工具輸入javajava -version命令查看是否輸出相關信息
  • JDK版本
  1. Java SE:Standard Edition,標準版
  2. Java EE:Enterprise Edition,企業版
  3. Java ME:Micro Edition,移動版
  • 編譯器使用IntelliJ IDEA,就不要再使用eclipse了。下載安裝破解可以在網上查找資源
    在這裏插入圖片描述

java程序

基礎部分

  • java程序的基本結構如上圖所示,一個基本的java程序由類、方法、成員變量組成
  • 和所有語言類似,java中的變量、數據類型、整數浮點數運算、布爾運算就不再贅述
    如有疑問可以查看教程

包裝類型

  • 我們常見的int float 變量不能視作對象(類),但是可以通過封裝成對應的類並實例化實現,也叫作包裝類型,JDK爲每種基本類型都創建了對應的包裝類型:
    在這裏插入圖片描述
  • 相互轉化
	int a = 10;
	Integer n = Integer.valueOf(a);
	Integer n1 = Integer.valueOf("100");
	
	int b = n.intValue();
	int c = Integer.parseInt("100");
	
	String str = n.toString();
	
	Integer n = 99;		// 自動裝箱
	int i = n;			// 自動拆箱	(這些都會影響效率,java是強類型語言)

Integer prop = Integer.getInteger(“cpus”); // 從系統環境中讀取環境變量

String

  • 在java中,字符串屬於引用類型,Java 提供了 String 類來創建和操作字符串
	public class StringDemo {
	    public static void main(String[] args) {// 字符串要使用雙引號
	        String s = "Hello";     // 字符串屬於引用類型,將引用類型賦給變量時:
	        String t = s;           // 變量t和s同時指向字符串Hello,而不是t重新開闢內存
	        s = "World";            // 變量s指向 World,t仍指向 Hello
	        System.out.println(s);  // World
	        System.out.println(t);  // Hello    引用類型類似指針,不產生任何副本
	    }
	}	// 可以理解爲:普通變量是持有某個值(可以重寫),字符串變量是指向某個值(可以重定向)

字符串的相關方法和原理可以查看:引文
常見的有substring() replace()

  • StringBuilder類
package Hello;

public class hello {
    public static void main(String[] args) {
        String name = "Roy";
        StringBuilder str = new StringBuilder();// 可變對象,可以高效拼接字符串(少佔內存)
        str.append("Hello!").append(name).append("你最帥");// 支持鏈式操作(返回this)
        System.out.println(str);
    }
}

Array

  • 數組變量使用“類型[ ]”標識
	int[] arr = new int[5]; // 數組初始化
        arr[0] = 1;     	// 數組是統一類型的數據集合
        arr[1] = 2;     	// 可以通過索引訪問
        arr[2] = 3;     	// 一旦創建大小不可改變
        arr[3] = 4;
        arr[4] = 5;
    int[] arr1 = {1,2,3,4,5};   // 也可以使用這種方式創建並賦值
    arr1 = new int[]{1,2,3};    // 數組也是引用類型,arr1重新指向了新的對象
    System.out.println(arr1.length);    // 打印數組長度
    System.out.println(arr1);   // 直接打印數組變量在JVM中的地址[I@6acbcfc0
    System.out.println(Arrays.toString(arr1));  // 快速輸出數組內容

	int[][] arr2 = {	// 二維數組
                {1,2,3,4,5},
                {3,4,5,6,7},
                {5,6,7,8,9}
    };
    System.out.println(Arrays.deepToString(arr2));  // 打印多維數組
注:java是強類型語言,每個變量前面必須限定類型
  • 輸入輸出
    import java.util.Scanner;
    
    Scanner scanner = new Scanner(System.in);
    System.out.println("Input your name:");
    String name = scanner.nextLine();	// 輸入字符類型
    System.out.println("Input your age: ");
    int age = scanner.nextInt();		// 輸入int型
    System.out.println(name+", you already "+age+"years old");
	double d = 3.14159;
    System.out.print(d);    // 輸出不換行
    System.out.printf("d: %.2f\n", d);  // d: 3.14 格式化輸出
    System.out.printf("d: %5.2f\n", d); // d:  3.14
  • 條件判斷
	public class conditionDemo {
	    public static void main(String[] args) {
	        String s1 = "Hello";
	        String s2 = "World";
	        if (s1 == s2) {
	            System.out.println("引用類型使用‘==’表示指向同一個對象");
	        }else if (s1.equals(s2)) {
	            System.out.println("判斷內容相等需要使用equals()方法");
	        }
	        else if (s1 != null && s1.equals(s2)) {
	            System.out.println("當變量爲null時equals()方法會報錯,所以使用短路運算符");
	        }else {
	            System.out.println("也可以將字符串對象放在前面");
	        }

			double d = 1 - 9.0/10;
	        System.out.println(d);  // 浮點運算存在誤差
	        if (Math.abs(d - 0.1) < 0.0001) {   // 需要使用絕對值函數判斷
	            System.out.println("d is 0.1");
	        }else {
	            System.out.println("d is not 0.1");
	        }
	    }
	}
  • 循環
	public class foreachDemo {
	    public static void main(String[] args) {
	        int[] num = {1,2,3,4,5};
	        for (int n : num){        // 也叫作增強型for循環,可以循環List/Map,因此循環是無序的
	            System.out.println(n);
	        }
	    }
	} // continue 可以結束本次循環,進行下一次循環
  • 命令行參數
	public class ArgsDemo { // 命令行參數是 String[]
	    public static void main(String[] args) {	// 類似於python中的*args和**kwargs
	        System.out.println("Number of args: "+ args.length);
	        for (String arg : args) {
	            if (arg.equals("-version")) {
	                System.out.println(arg);
	            }
	        }
	    }
	}
	// 命令行參數由JVM傳遞給main方法
	// 使用快捷鍵[Alt+F12]即可在IDEA中調出命令行,輸入:java ArgsDemo.java -version -s -t "Hello" 查看輸出
	// javac 文件名.java 可以將java文件編譯成.class文件

數據封裝

  • 公有方法和私有方法,通過方法訪問成員變量
  • 構造方法
  • 方法重載
package Hello;
// 一切皆對象Object
public class Person {   // 數據封裝
    public String name;
    public int age;

    public Person(String name, int age) {   // 構造方法:可以在實例化時初始化成員變量的值
        this.name = name;
        this.age = age;
    }

    public Person() {  // 多個構造方法,實例化時可以根據參數的數量和位置自動選擇合適的構造方法
        this("Roy",22); // 通過this進行實例化
    }

    public void setName(String name){   // 外部對象一般通過public修飾的方法訪問成員變量
        this.name = name;
    }
    // 方法重載:功能相同的函數使用相同的名字
    public void setName() {     // 主要依靠參數類型和數量區分
        System.out.println("這是setName方法的重載");
    }

    public String getName() {
        return this.name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    private int calcBirth(int age) {
        return 2020 - age;
    }

    public int getBirth(int age){ // 內部方法可以調用私有方法
        return calcBirth(age);
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person.name + person.age);// Roy22
        person.setAge(18);
        person.setName("Roy");
        System.out.println("Your name is " + person.getName());
        // 公有方法調用私有方法
        System.out.println("Your birthday is " + person.getBirth(23));
    }
}

繼承

  • 繼承是一種代碼複用的方式
  • 一個類只能有一個父類,所有的類均繼承自Object類,形成一個繼承樹:
  • Object——Person——Girl & Boy
package Hello;
// 一切皆對象Object
public class Person /* extends Object */{
    public String name;
    public int age;

    protected int speed;    // protected 把變量和方法都控制在繼承樹內部

    public Person(String name, int age) {   // 構造方法:可以在實例化時初始化成員變量的值
        this.name = name;
        this.age = age;
    }

    public Person() {   // 多個構造方法,實例化時可以根據參數的數量和位置自動選擇合適的構造方法
        this("Roy",22); // 通過this進行實例化
        System.out.println("自動調用父類的無參數構造器");
    }

    public void run() {
        System.out.println("衝鴨!");
    }
}

package Hello;

public class Girl extends Person {
    String name;
    int age;

    public Girl(String name, int age) { // 構造方法
    	// 會自動調用父類的無參數構造方法,相當於super()
    	// 如果父類沒有無參的構造方法,必須調用父類的有參構造方法!
        this.name = name;
        this.age = age;
    }

    public void run() {     // 繼承並重寫父類的方法
        super.run();		// 複用了父類的代碼,提高效率
        System.out.println("女孩向前衝!");
    }
}

package Hello;

public class Boy extends Person {
    String name;
    int age;

    public Boy(String name,int age) {
        super("father",88); // 調用父類中有參數的構造方法
        this.name = name;
        this.age = age;
    }

    public void run() {     // 繼承並重寫父類的方法
        super.run();        // super關鍵字調用父類的成員
        System.out.println(super.speed);    // 子類不能調用父類的private變量,但可以使用protected變量
        System.out.println("男孩向前衝!");
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Person person = new Person("Roy",18);
        Boy boy = new Boy("John",16);
        Girl girl = new Girl("Diana",16);
        boy.run();
        girl.run();
    }
}
/* 輸出:
父類的無參數構造器
衝鴨!
0
男孩向前衝!
衝鴨!
女孩向前衝! */
  • 注意區分繼承和組合的關係,繼承是is,擁有相同特性的類之間的從屬關係;而組合是has,可以通過在類中實例化其對象實現
  • 繼承往往和多態相聯繫,多態有三要素:1.要有繼承關係 2.要有子類重寫父類成員方法 3.要有父類數據類型引用至子類

轉型

package Hello;

public class Main {
    public static void main(String[] args) {
        // 轉型
        Person ps = boy;    // 向上轉型(子類變成父類)
        ps.run();   // 衝鴨!
        Boy by = (Boy) person;    // 向下轉型(父類變成子類),必須強制
        // 由於子類不一定實現了父類的所有方法,所以會拋出異常
        by.run();   // ClassCastException
    }
}

抽象類

  • 定義了抽象方法的類就是抽象類,必須使用abstract修飾
  • 抽象類是爲了更加靈活地實現多態特性(子類可以控制父類的方法)
  • 抽象方法相當於定義了子類必須實現(重寫)的接口規範
package Hello;

public abstract class CalcArea {	  // 抽象類
    public abstract double area();    // 抽象方法,沒有任何實現的代碼
    
    public double perimeter() {       // 可以定義非抽象方法
        return 0;
    }
}
package Hello;

public class RectArea extends CalcArea{
    private final double width;	// final修飾成員變量,必須要賦初始值,且只能初始化一次
    private final double height;// 所以必須使用有參構造方法賦值
    // final修飾類的時候,表示這個類不能被繼承,類中的成員方法都會被隱式的指定爲final方法
    // final修飾的方法不能被重寫

    public RectArea(double width,double height) {
        this.width = width;
        this.height = height;
    }
    @Override
    public double area() {    // 實現父類的抽象方法
        return this.height * this.width;
    }
}
package Hello;

public class CircleArea extends CalcArea{
    public double redius;

    public CircleArea(double redius) {
        this.redius = redius;
    }
    @Override
    public double area() {
        return Math.PI * redius * redius;
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        CalcArea Circle = new CircleArea(5);  // 調用的是子類的方法,但實例化爲抽象類即可(因爲實現了所有父類的方法,可以向上轉型)
        CalcArea Rect = new RectArea(5,5);    // 我們只關心是否實現了抽象類的方法
        System.out.println(Circle.area());    // 具體的實現完全由不同子類承擔,功能各異
        System.out.println(Rect.area());      // 更加靈活的實現了多態的特性
    }
}

接口

  • 接口定義了純抽象的規範,使用interface關鍵字修飾
  • 一個類可以實現多個接口,使用implement
  • 接口也是數據類型,適用於向上向下轉型
  • 接口不能定義實例字段(即只能定義方法)
  • 接口可以定義default方法,實現接口的類可以不用實現default方法
package Hello;

public interface InterfaceDemo {
    double area();    // 接口方法

    default double perimeter(){     // default方法,執行接口的類不用實現
        return 0;
    }
}
package Hello

public class CircleArea implements InterfaceDemo{  // 實現接口
    public double redius;

    public CircleArea(double redius) {
        this.redius = redius;
    }

    @Override
    public double area() {
        return Math.PI * redius * redius;
    }
}
  • 接口可以繼承接口實現接口的擴展
package Hello;

public interface InterfaceDemo1 extends InterfaceDemo{
    int speed();
}
public class CircleArea implements InterfaceDemo1{  // 實現接口
    public double redius;

    public CircleArea(double redius) {
        this.redius = redius;
    }

    @Override
    public double area() {
        return Math.PI * redius * redius;
    }

    @Override
    public int speed() {
        return 0;
    }
}
  • 接口的層次代表了抽象的程度(可以先不理解)
  • 接口與抽象類的區別:
    在這裏插入圖片描述

靜態字段和方法

  • 使用static修飾的字段和方法
  • 普通字段在每個實例中都有自己的一個“獨立空間”
  • 靜態字段只有一個“共享空間”,所有實例都共享該字段
    在這裏插入圖片描述
package Hello;

public class Person {
	static int number;
	// 靜態方法
    public static int getNumber() {
        return ++number;
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person();
        Person.number++;		// 類名訪問靜態變量
        System.out.println(Person.getNumber());
        Person p2 = new Person();
        Person.number++;
        System.out.println(Person.getNumber());
        Person p3 = new Person();
        Person.number++;
        System.out.println(Person.getNumber());
    }
}

  • 不推薦使用實例對象訪問靜態字段,因爲實例本身並沒有靜態字段,也是由編譯器轉化爲類名來訪問。推薦直接使用類名訪問!
  • 調用靜態方法不需要實例對象
  • 靜態方法通常用於工具類,例如:Arrays.sort() / Math.random()

  • 我們自定義的類名可能與java中或其他人的類名衝突,這是就需要定義包package,上面的每一個小例子都在包Hello
  • java加載class並執行代碼時,總是使用類的完整類名,比如java.util.AraysHello.Person,這樣就避免了重複命名引起衝突(類似於命名空間的概念),也因此,包沒有繼承關係!
  • 位於同一個包的類,可以訪問包作用域的字段和方法
  • 前面使用了public/protected/private都代表了字段或方法不同的作用域,在一個包中不使用這些修飾的就默認在包的作用域

注:如果不能確定是否使用public方法,就不要使用,否則會暴露方法的

在這裏插入圖片描述

  • java的核心類放置在java.lang
    在這裏插入圖片描述
  • java文件的存放要按照包名的層次關係
    在這裏插入圖片描述

classpath

  • 是一個環境變量,指示如何搜索class
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 我們通常引入jar包避免大量的目錄和.class文件
    在這裏插入圖片描述
  • 創建jar包可以使用自帶的jar命令,或者使用構建工具如Maven
  • jar中可以包含一個特殊的 MANIFEST.MF 文件,用於指定Main-class等
  • JDK自帶的class被打包在rt.jar中

JavaBean

  • 在這裏插入圖片描述
  • 命名規範:成員變量私有化,使用類的getter/setter方法訪問

enum常量

public enum Weekday {
    SUN("星期天"), MON("星期一"), TUE("星期二"), WED("星期三"), THU("星期四"), FRI("星期五"), SAT("星期六");

    private String chinese; // 定義私有變量

    private Weekday(String str){// 定義構造方法
        this.chinese = str;
    }
    
    public String toChinese(){
        return this.chinese;
    }
}
package Hello;

public class Main {
    public static void main(String[] args) {
        Weekday sun = Weekday.SUN;
        System.out.println(sun.toChinese());// 星期天
        System.out.println(sun.name());     // SUN (不推薦使用toString())
}
  • 在這裏插入圖片描述
  • 可以理解爲以類形式封裝的常量

常用工具類

  • Math
  • Random
  • 在使用過程中積累即可!

推薦廖雪峯老師的教程
下節繼續
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章