JAVA 筆記

JAVA Jun 15, 2019

事前準備

IDE - 整合開發環境

先下載IntelliJ IDEA作為JAVA開發平台,下載地址:

https://www.jetbrains.com/idea/download/#section=windows

開始安裝 
設定安裝選項 
完成安裝 
打開並跳過所有設定 

建立新專案時發現沒装JDK,要到官網下載

<No SDK>
下載JDK 

課程準備

這次選擇的課程為Udemy的Java Tutorial for Complete Beginners 免費課程,由零學起。

課程連結: https://www.udemy.com/java-tutorial/learn/lecture/131404

Overview:

Learn to program in the Java programming language. This course assumes no prior programming knowledge, just a desire to learn to program.
您會學到什麼Learn to program in Java
有任何課程要求或先決條件嗎?Basic fluency with computers
此課程適合哪些人:Anyone who wants to learn Java

//15-6-2019


基礎課題

Helloworld

先來一個helloworld

Add a new Java Class
找到些常用快捷鍵
psvm:public static void main(String[] args) {}
sout:System.out.println();

Hello World:

public class Application {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

Variables

定義及顯示變數

public class Application {
    public static void main(String[] args) {
        int myNumber = 88;
        myNumber = 20;
        System.out.println(myNumber);
    }
}

多種Primitive變數

public class Application {
    public static void main(String[] args) {
        //more about data types: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
        int myNumber = 88; //
        short myShort = 23;
        long myLong = 10;
        double myDouble = 2.656568646;
        float myFloat = 2.521312f;
        char myChar = 'x';
        boolean myBoolean = true;
        byte myByte = 127;

        System.out.println(myNumber); //88
        System.out.println(myShort);  //23
        System.out.println(myLong);   //10
        System.out.println(myDouble); //2.656568646
        System.out.println(myFloat);  //2.521312
        System.out.println(myChar);   //x
        System.out.println(myBoolean);//true
        System.out.println(myByte);   //127
    }
}

non-primitive變數

String:

public class Application {
    public static void main(String[] args) {
        String text = "Hello";
        String blank = " ";
        String name = "ken";
        String greeting = text + blank + name;
        System.out.println(greeting); //Hello ken
    }
}

註:single quote用於char, double quote用於String

While loop

public class Application {
    public static void main(String[] args) {
        int value = 0;
        while (value < 10){
            System.out.println("Hello" + value);
            value++;
        }
    }
}
Hello0
Hello1
Hello2
Hello3
Hello4
Hello5
Hello6
Hello7
Hello8
Hello9

For loop

public class Application {
    public static void main(String[] args) {
        for(int i=0; i<5; i++){ //start,condition to run,step
            System.out.println("Hello" + i);
        }
    }
}
Hello0
Hello1
Hello2
Hello3
Hello4

Printf(%d)

不換行, syntax:System.out.printf(format, arguments);

public class Application {
    public static void main(String[] args) {
        for(int i=0; i<5; i++){
            System.out.printf("Hello %d",i);
        }
    }
}
Hello 0Hello 1Hello 2Hello 3Hello 4

為何用 %d ?

s – formats strings
d – formats decimal integers
f – formats the floating-point numbers
t– formats date/time values
more:https://pydoing.blogspot.com/2011/01/java-printf.html

\n換行

public class Application {
    public static void main(String[] args) {
        for(int i=0; i<5; i++){
            System.out.printf("Hello %d\n",i);
        }
    }
}
Hello 0
Hello 1
Hello 2
Hello 3
Hello 4

If...then...else

public class Application {
    public static void main(String[] args) {
        int value = 0;
        if(value < 0){
            System.out.println("It's smaller than 0");
        }else if(value > 10){
            System.out.println("It's larger than 10");
        }else{
            System.out.println("It's between 0 and 10");
        }
    }
}
It's between 0 and 10

Break a loop using if

public class Application {
    public static void main(String[] args) {
        int counter = 1;
        while(true){
            if(counter <= 10){
                System.out.printf("Counter is %d\n",counter);
                counter++;
            }else{
                break;
            }
        }
    }
}
Counter is 1
Counter is 2
Counter is 3
Counter is 4
Counter is 5
Counter is 6
Counter is 7
Counter is 8
Counter is 9
Counter is 10

Scanner讀取輸入

import java.util.Scanner;

public class Application {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        System.out.println("Enter something: ");
        String value = reader.nextLine(); //double value = input.nextDouble(); for double, int value = input.nextInt(); for int
        System.out.println("You entered " + value);
    }
}
Enter something: 
Hello
You entered Hello

Do...while

import java.util.Scanner;

public class Application {
    public static void main(String[] args) {
        int value = 0;
        Scanner reader = new Scanner(System.in);
        do{
            System.out.println("Enter 5:");
            value = reader.nextInt();
        }while(value != 5);
        System.out.println("You entered 5 finally.");
    }
}
Enter 5:
10
Enter 5:
8
Enter 5:
3
Enter 5:
5
You entered 5 finally.

Switch

import java.util.Scanner;

public class Application {
    public static void main(String[] args) {
        int value = 0;
        Scanner reader = new Scanner(System.in);
        System.out.printf("Enter 1-3: ");
        value = reader.nextInt();
        switch(value){
            case 1: //can only be constant
                System.out.println("First option");
                break;
            case 2:
                System.out.println("Second option");
                break;
            case 3:
                System.out.println("Third option");
                break;
            default: //else
                System.out.println("Invalid choice");
        }
    }
}
Enter 1-3: 4
Invalid choice

Array and loop of items(1)

public class Application {
    public static void main(String[] args) {
        int numbers[];
        numbers = new int[3];
        System.out.println(numbers.length);

        numbers[0] = 0;// array starts from 0
        numbers[1] = 100;
        numbers[2] = 200;
        //or int numbers[] = {0,100,200}; to declear a array with content
        for(int i=0; i<numbers.length; i++){
            System.out.printf("Number %d is %d.\n",i,numbers[i]);
        }
    }
}
3
Number 0 is 0.
Number 1 is 100.
Number 2 is 200.

//19-6-2019

Array of Strings and loop of items(2)

public class Application {
    public static void main(String[] args) {
        String[] list = new String[3]; //allocate memory for address
        list[0] = "item one"; //point the item in array to memory address that hold the string "item one"
        list[1] = "item two";
        list[2] = "item three";
        //or String[] list = {"item one","item two","item three"}
        for(String item: list){
            System.out.println(item);
        }
    }
}
item one
item two
item three

Multidimensional array(string) and loop of items(1)

public class Application {
    public static void main(String[] args) {
        String[][] list = new String[3][2];
        list[0][0] = "milk";
        list[0][1] = "cookie";
        list[1][0] = "cake";
        list[1][1] = "candy";

        for(int row=0; row<list.length; row++){
            for(int col=0; col<list[row].length; col++){
                System.out.print(list[row][col] + "\t");
            }
            System.out.println();
        }
    }
}
milk	cookie	
cake	candy	
null	null

Multidimensional array(int) and loop of items(2)

public class Application {
    public static void main(String[] args) {
        int map[][] = {
                {1,2,3},
                {4,5},
                {6,7,8,9}
        };
        System.out.println(map[1][0]);

        for(int[] row: map){ //for every row(int[])
            for(int col: row){ // for every item in row
                System.out.print(col + "\t");
            }
            System.out.println();
        }
    }
}
4
1	2	3	
4	5	
6	7	8	9	

Multidimensional array without declaring the size of second dimension

public class Application {
    public static void main(String[] args) {
        //second dimension of array can be left as blank
        String[][] list = new String[2][];
        list[0] = new String[3];
        list[1] = new String[5];
        list[0][2] = "butter";


        for(int row=0; row<list.length; row++){
            for(int col=0; col<list[row].length; col++){
                System.out.print(list[row][col] + "\t");
            }
            System.out.println();
        }
    }
}
null	null	butter	
null	null	null	null	null

OOP概念

Class

Class可視為一個建立object的範本(template for creating objects,while everything in java is an object)或一種類型(type),如String,int,double等。
Class可包含data(state)和method(subroutines),Animals class中的data就是name,mammal,legs

class Animal{
    String name;
    boolean mammal;
    int legs;
}

public class Application {
    public static void main(String[] args) {
        Animal dog = new Animal();
        dog.name = "prince";
        dog.mammal = true;
        dog.legs = 4;

        Animal fish = new Animal();
        fish.name = "dory";
        fish.mammal = false;
        fish.legs = 0;

        System.out.println(dog.name);
        System.out.println(fish.legs);
    }
}
prince
0

Method

Method (sayHello,info) 像一個寫在Class中的程序,用Class的instance variable (name,mammal,legs),會在主程序呼叫並執行。
Method必定有(),如sayHello()

class Animal{
    String name;
    boolean mammal;
    int legs;

    void info(){
        if (mammal) {
            System.out.println(name + " is a mammal. It has " + legs + " legs.");
        }else{
            System.out.println(name + " is not a mammal. It has " + legs + " legs.");
        }
    }

    void sayHello(){
        System.out.println("Hello, I am " + name);
    }
}

public class Application {
    public static void main(String[] args) {
        Animal dog = new Animal();
        dog.name = "prince";
        dog.mammal = true;
        dog.legs = 4;
        dog.sayHello();
        dog.info();

        Animal fish = new Animal();
        fish.name = "dory";
        fish.mammal = false;
        fish.legs = 0;
        fish.sayHello();
        fish.info();
    }
}
Hello, I am prince
prince is a mammal. It has 4 legs.
Hello, I am dory
dory is not a mammal. It has 0 legs.

Getter and return values

Method中的void所指的是不回傳任何值,可改為intString等字眼再加return來回傳值。

class Animal{
    String name;
    int legs;

    String getName(){
        return name;
    }

    int getLegs(){
        return legs;
    }
}

public class Application {
    public static void main(String[] args) {
        String animalName;
        int animalLegs;

        Animal dog = new Animal();
        dog.name = "prince";
        dog.legs = 4;
        animalName = dog.getName();
        System.out.println("Name of dog: " + animalName);

        Animal fish = new Animal();
        fish.name = "dory";
        fish.legs = 0;
        animalLegs = fish.getLegs();
        System.out.println("Number of legs of fish: " + animalLegs);
    }
}
Name of dog: prince
Number of legs of fish: 0

Method Parameter

可以在主程序傳參數到Method

class Robot{
    public void speak(String text){
        System.out.println(text);
    }

    public void jump(int height){
        System.out.println("Jumping: " + height);
    }

    public void move(String direction, double distance){
        System.out.println("Move " + distance + " meters toward " + direction);
    }
}

public class Application {
    public static void main(String[] args) {
        Robot sam  = new Robot();
        sam.speak("Hello");
        sam.jump(8);
        String face = "south";
        sam.move(face,10.2);
    }
}
Hello
Jumping: 8
Move 10.2 meters toward south

Setter and "this"

在不知Class裏定義的instance variable名稱下,Setter仍可以改變該variable,如ken.setAge(20),可改變object(ken)的Age。

若設Class裏面的instance  variable為private,如private int age,稱為封裝(encapsulation)。

在Method中,若parameter跟instance variable相同,instance variable 需用上this.variablethis所指的是目前的object,如this.age = age

class Snack{
    private String name;
    private int quatity;

    public void setName(String name){
        this.name = name;
    }
    public void setQuantity(int number){
        quatity = number;
    }
    public String getName(){
        return name;
    }
    public  int getQuantity() {
        return quatity;
    }
}

public class Application {
    public static void main(String[] args) {
        Snack cookie = new Snack();
        cookie.setName("cookie");
        cookie.setQuantity(5);
        System.out.println(cookie.getName());
        System.out.println(cookie.getQuantity());
    }
}
cookie
5

Constructor

Constructor不會回傳任何值,連void也不用打,如public Snack(),但constructor必需與Class同名。另外,Constructor會在object創建時自動運行,不論有沒有指派變數。一個Class可以有多個constructor,但要每個constructor的parameter都不相同。

若要在constructor(1)內喚叫另一個constructor(2),就要輸入this(),不像Main裏面使用的Snack() 。另外,需將呼叫constructor(2)的代碼放到constructor(1)的最上方。

class Snack{
    public Snack(){
        this(0);
        System.out.println("Constructor 1");
    }
    public Snack(int number){
        System.out.println("Constructor 2");
        System.out.println("Quantity: " + number);
    }
}

public class Application {
    public static void main(String[] args) {
        Snack candy = new Snack();
        new Snack(1);
    }
}
Constructor 2
Quantity: 0
Constructor 1
Constructor 2
Quantity: 1

Static

Static variable或method可視為一個Class中共用的variable/method,每項object都適用。

Class中的一般變數(instance variable)在每一個object都可以不同,但在每個object的某個static variable就只可有同一個數值。

Static method只可用static variable,不可用instance variable,但instance method 可用static variable。

class Student{
    public static String school = "HKNOIT";
}

public class Application {
    public static void main(String[] args) {
        System.out.println(Student.school);
    }
}
HKNOIT

Static variable可用於Class外存取的constant,如Math.PI,Syntax:public final static string GREETING = "Hello everyone, I come from HKNOIT",在Class外呼叫就用ClassName.GREETING

final 是 constant 的 datatype
class Student{
    public final static String GREETING = "Hello everyone, I come from HKNOIT";
}

public class Application {
    public static void main(String[] args) {
        System.out.println(Student.GREETING);
    }
}
Hello everyone, I come from HKNOIT

Static variable也可用於counting,統計創建了多少個object及分配id。

class Student{
    public static int counter;
    public String name;
    public int age;
    public int uid;

    Student(String name,int age){
        counter ++;
        this.name = name;
        this.age = age;
        uid = counter;
    }
}

public class Application {
    public static void main(String[] args) {
        System.out.println("UID\tName\tAge");
        Student ken = new Student("Ken",10);
        System.out.println(ken.uid + "\t" + ken.name + "\t" + ken.age);
        Student allen = new Student("Allen",12);
        System.out.println(allen.uid + "\t" + allen.name + "\t" + allen.age);
    }
}
UID	Name	Age
1	Ken	10
2	Allen	12

String builder

每次"改變"一個String,其實是創建了一個新的String,再將string assign到同一個variable,會浪費memory,而使用StringBuilder就能解決此問題。

public class Application{
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("Hello");
        sb.append(" ");
        sb.append("I am Ken.");
        //or simply sb.append("Hello").append(" ").append("I am Ken.");
        System.out.println(sb.toString());
    }
}
Hello I am Ken.

String Formatting(ref. to printf)

%2d 代表預留最多兩個空位
%-2d 代表內容置左
%.1f 代表只取一個小數位(四捨五入)
可合併為%-2.1f  

public class Application{
    public static void main(String[] args) {
        System.out.print("Some text\tafter a tab\nafter a line break.");
        System.out.println("Print and start a new line");
        for(int i=9;i<12;i++){
            System.out.printf("%-2d:%s\n",i,"Some text.");
        }
        System.out.printf("Round a value at 1 decimal place and length is 5:%5.1f",3.8522);
    }
}
Some text	after a tab
after a line break.Print and start a new line
9 :Some text.
10:Some text.
11:Some text.
Round a value at 1 decimal place and length is 5:  3.9

//20-6-2019

"toString" method

用toString來顯示string格式的object(get the string representation of the object), 可用於Debug。

class Member{
    int age;
    String name;

    public Member(int age,String name){
        this.age = age;
        this.name = name;
    }
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append(name).append(" is ").append(age).append(" years old.");
        return sb.toString();
    }
}

public class Application{
    public static void main(String[] args) {
        Member ken = new Member(16,"Ken");
        System.out.println(ken);
    }
}
Ken is 16 years old.

Inheritance

public class xxx extends yyy,所指的是xxx(child)是yyy(parent)的child class,xxx會繼承yyy的method,可用此來延伸或覆寫(final) class,包含/改變原本的method和添加新的method。
若要在child class使parent class的method,parent class method所用的variable一定要是protectedpublic

Main.java

public class Application{
    public static void main(String[] args) {
        Machine m1 = new Machine();
        m1.start();
        m1.stop();

        Car car1 = new Car();
        car1.start();
        car1.playMusic();
        car1.stop();
    }
}

Machine.java

public class Machine {
    public void start(){
        System.out.println("Machine start");
    }
    public void stop(){
        System.out.println("Machine stopped");
    }
}

Car.java

public class Car extends Machine{
    public void playMusic(){
        System.out.println("do ra me");
    }
}
Machine start
Machine stopped
Machine start
do ra me
Machine stopped

Overwrite

覆寫method時,需在Declare前加上@Overwrite 及有與parent class相同的method名稱。
另外,別覆寫variable。

Main.java和Machine.java與上面相同;
Car.java

public class Car extends Machine{
    public void playMusic(){
        System.out.println("do ra me");
    }

    @Override
    public void start() {
        System.out.println("Car Starting");
    }
}
Machine start
Machine stopped
Car Starting
do ra me
Machine stopped

Package

Package的用途是方便組織代碼和避免Class Name的衝突,就像一個資料夾,package name多數只會用一些很簡單的英文字,而且全小寫。
在Package apple要用Package banana 的Class就要用import banana.xxx;
因為Package名必需是獨特來避免與別人的Package產生衝突,所以通常Package都會用倒轉(應該是因為sub package要不同,但parent package名想保持相同?)的域名來命名,如com.example.app

添加新的Package:Right click 'src' > New > Package
ocean是package,plants是ocean的sub package,Fish是ocean package下的class,Application為預設package下的class

Import Packages:

import ocean.Fish;
import ocean.plants.Algae;

public class Application{
    public static void main(String[] args) {
        Fish fish = new Fish();
        Algae algae = new Algae();
    }
}

//21-6-2019

Interface(& abstract class)

Interface大概是作為一個中介媒體,可以讓未知類別(datatype)但method相似的class用上同一Method來呼喚,隱藏當中的機制。

讀寫檔案 讀寫RS232 讀寫USB 讀寫Socket ......     雖然其運作方式皆不同 (低階 asmbely)     但是使用者使用起來都是一樣 用 open read write close (高階語言)     最重要的就是中間的機制 (作業系統裡的driver,C++裡的 virtual function)
Reference:http://www.programmer-club.com.tw/ShowSameTitleN/c/15743.html

影片只提及Interface,一查發現interface跟abstract class原來差不多,而不同的地方是——由於class 只可承繼(inherit)一個parent,所以class只可以extends一個abstract class,但若有多個不同的"種類"要承繼,就要用上interface。
Reference:https://www.w3schools.com/java/java_interface.asp

在求圖形的面積方面,長方形與三角形同是要求長和闊,但計法卻相異,都會用上findArea,此時可用interface(or abstract class)解決。(基於影片教的是interface,這裏我用interface做。)

Main.java:

public class Application{
    public static void main(String[] args) {
        Triangle tri = new Triangle(10,20);
        Rectangle rec = new Rectangle(10,20);

        outputArea(tri);
        outputArea(rec);
    }
    private static void outputArea(Shape shape){
        System.out.println(shape.findArea());
    }
}

Triangle.java

public class Triangle implements Shape {
    private int width;
    private int height;
    public Triangle(int width,int height){
        this.width = width;
        this.height = height;
    }
    public double findArea(){
        return height*width/2;
    }
}

Rectangle.java

public class Rectangle implements Shape{
    private int width;
    private int height;
    public Rectangle(int width,int height){
        this.width = width;
        this.height = height;
    }
    public double findArea(){
        return height*width;
    }
}

Shape.java(interface)

public interface Shape {
    double findArea();
}
100.0
200.0

Public, Private, Protected

若variable/method declare為public,可從任何地方存取。
若variable/method declare為private,則只可以在同一class內存取。
若variable/method declare為protected,則可由同一class或subclass或同一package內存取。
若無declare,如int number;,則可由同一class內存取,但無法透過extends存取number

Polymorphism

Polymorphism所指的是可用superclass的地方(datatype of superclass)都可用subclass。當一個superclass type的object被declare為supclass的type時(如 Plant plant1 = new Tree();),可以用superclass和supclass(override)都有的method(如grow),這樣會執行supclass的(override)method而非superclass的method。但若果該object想用只有supclass才有的method(shedLeave),就會發生錯誤。

Reference + Code:https://www.caveofprogramming.com/java-video/java-for-complete-beginners-video-part-26-polymorphism.html

Encapsulation

Encapsulation所指的是將敏感內容在用戶方隱藏,可將variable或method declare為private,加以getter和setter取得改變或查詢private variable。

public class Person {
  private String name; // private = restricted access

  // Getter
  public String getName() {
    return name;
  }

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

Java API

Java API即是Java預先寫好的package、class、method的資料庫(library),如scanner、string等。

Casting of numerical values

Java有short,int,long,double,float,byte的數值,部份可以互相轉換(cast),如int類型轉long類型用intValue = (int)longValue,有些則無需要打(typeToCast),如double轉int,Java會自動將doubleValue的小數除去(intValue = doubleValue)。

但不能用此方法轉int為String,只能在numerical values中轉換。 另外若強行轉換(如將int轉為byte),而該variable(byte range: -128 to 127)無足夠memory去承載,轉換出來的值會是該data type的最小值(即-128)。

Upcasting and Downcasting

Upcasting所指的是將child class視為parent class看待,基於polymorphism,所有parent class的method都可在child class中使用(因為parent class有的method,child class都有),故不會有錯誤,但跟polymorphism一樣,parent class只可用自己有的method。

Downcasting所指的是將parent class視為child class看待(Camera camera2 = (Camera)machine2;),但因為parent class未必有child class的method,所以downcasting後會有機會發生錯誤,要用(type_to_convert)來強行轉換。

class Machine{
    public void start(){
        System.out.println("Machine started.");
    }
}

class Camera extends Machine{
    public void start(){
        System.out.println("Camera started");
    }
    public void snap(){
        System.out.println("Photo taken.");
    }
}

public class Application{
    public static void main(String[] args) {
        Camera camera1 = new Camera();
        //upcasting - camera casted to machine
        Machine machine1 = camera1;
        machine1.start();
        //error occurs because type of variable decide what method could be called.
        //machine1.snap();

        //downcasting - working
        Machine machine2 = new Camera();
        Camera camera2 = (Camera)machine2;
        camera2.start();
        camera2.snap();

        //downcasting - not working
        Machine machine3 = new Machine();
        Camera camera3 = (Camera)machine3;
        camera3.start();
        camera3.snap();
    }
}
Camera started
Camera started
Photo taken.
Exception in thread "main" java.lang.ClassCastException: class Machine cannot be cast to class Camera (Machine and Camera are in unnamed module of loader 'app')
	at Application.main(Application.java:33)

Generics & wildcard

Generics指的是一個method可接受多種不同的object,如integer、string等,但都要在declare時定義好可接受的datatype,常見例子有ArrayList。

在generics中,如ArrayList,可將會接受的datatype定為"?"(wildcard),代表接受任何objects,但所用的method都只可為object的method。可配搭super或extends來篩選class。

import java.util.ArrayList;
class Machine{
    public String toString(){
        return "I am a machine";
    }
    public void start(){
        System.out.println("Machine started");
    }
}

class Camera extends Machine{
    public  String toString(){
        return "I am a camera";
    }
}

public class Application{
    public static void main(String[] args) {
        ArrayList<Machine> list1 = new ArrayList<>();
        list1.add(new Machine());
        list1.add(new Machine());

        ArrayList<Camera> list2 = new ArrayList<>();
        list2.add(new Camera());
        list2.add(new Camera());

        showList(list1);
        showList(list2);
        showList1(list1);
        showList1(list2);
        showList2(list1);
        showList2(list2);
    }
    //any objects, no specific methods
    public static void showList(ArrayList<?> list){
        for(Object value:list){
            System.out.println(value);
        }
    }
    //set upper bound, only parent class methods
    public static void showList1(ArrayList<? extends Machine> list){
        for(Machine value:list){
            System.out.println(value);
            value.start();
        }
    }
    //set lower bound, no specific methods
    public static void showList2(ArrayList<? super Camera> list){
        for(Object value:list){
            System.out.println(value);
        }
    }
}
Machine started
I am a machine
Machine started
I am a camera
Machine started
I am a camera
Machine started
I am a machine
I am a machine
I am a camera
I am a camera

標籤