JAVA 筆記
事前準備
IDE - 整合開發環境
先下載IntelliJ IDEA作為JAVA開發平台,下載地址:
https://www.jetbrains.com/idea/download/#section=windows
建立新專案時發現沒装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
找到些常用快捷鍵
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所指的是不回傳任何值,可改為int
或String
等字眼再加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.variable
,this
所指的是目前的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一定要是protected
或public
。
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
。
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