iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 7
2

寫在前面

在某段時間Java甚至是程式語言的代名詞,
曾經霸佔TOBIE第一名好幾年
直到最近因為疫情關係嵌入式系統需求量大增,才跟C語言交換了位置

https://ithelp.ithome.com.tw/upload/images/20200907/20127836aWLZwSGg1d.png

跨平台大概是JAVA最重要的特性,就如同他的口號

Write once, run anywhere

在智慧型手機興起前,各家廠商都是各自開發自己的系統
而當你需要在不同手機上執行同一個程式時,就可以使用JAVA
(還記得當年開遊戲時都會出現的咖啡杯嗎?)
之後雖然由Android跟iOS二分天下,但是由於JAVA跨平台的特性,得以在Android上繼續保留下來

玩過minecraft的都知道minecraft分為兩種版本:JAVA版跟C++版
JAVA版也是比較早期並且可以玩出許多花樣的版本

說了這麼多,就是為了要說明,當今天你有想要做的成品,卻又不知該從哪個語言開始寫(而且你又不會C++)時,就從JAVA來吧
畢竟當你完成後才發現這個成品應該是手機上的應用,或其他平台時,程式碼甚至都不必動就可以直接移植了

接著

讓我們開始吧

JAVA是一個編譯+直譯的語言,所有的java檔都必須先編譯成class檔,再由虛擬機進行直譯的動作

蛤? 為什麼要這麼麻煩?

理由在於如果是編譯式的語言雖然可以編譯成電腦可以執行的程式(比方說windows的.exe檔)
但是這個檔案一旦拿到linux上或Mac上就無法執行了
因此後來人們想出的方法是在每一台電腦上都安裝直譯器(像是python這種直譯語言)
接著你便可以帶著一份python的程式到各個不同作業系統的電腦上執行了
但是由於執行程式時會需要將程式碼一行一行轉成電腦可執行的程式,因此速度將對於編譯式語言會來得慢

因此我們有了混合式的JAVA,

先把原本的java檔先轉成java虛擬機看得懂的class檔,要執行時再交由java虛擬機來執行class檔

java虛擬機?

他有點像是如果你今天使用VMware或是VirtualBox,在電腦上虛擬出一個linux或windows一樣
只是今天你虛擬出來的是一台會執行class檔的電腦(他甚至有自己的CPU跟記憶體,只是都是虛擬出來的)
然後你在每一個平台上都這麼做就可以達到跨平台的要求了
而且由於class檔已經被編譯成機器看得懂的語言了(對於java虛擬機來說)
因此執行速度上當然比單純的直譯式語言快得多

還沒安裝的人先去安裝JAVA吧,
其他人我們繼續往下走

先在你的工作資料夾建立一個叫做convert.java的檔案,接著

貼上程式碼

import java.util.Scanner;
public class convert {
    public static void main(String[] args) {
       
        System.out.println("Tell me what you want to do:");
        System.out.println("(1)T to H (2)H to T");
        Scanner scanner = new Scanner(System.in);
        String choose = scanner.nextLine();

        switch(choose) { 
            case "1": 
                System.out.println("Please enter the number:");
                String input = scanner.nextLine();
                System.out.println(t2h(input));
                break;
            case "2": 
                System.out.println("Please enter the number:");
                String hex = scanner.nextLine();
                System.out.println(h2t(hex));
                break; 
            default: 
                System.out.println("輸入錯誤"); 
        }
    }

    public static String t2h(String input){
        int number = Integer.parseInt(input) ;
        for(int i = 0; i < 16; i++) {
            for (int j = 0; j <16; j++){
                for (int k = 0; k <16; k++){
                    if (Math.pow(16,2)*i+Math.pow(16,1)*j+Math.pow(16,0)*k == number){
                        return returnAE(i)+returnAE(j)+returnAE(k);
                    }
                }
            }
        }
        return "";
    }

    public static String returnAE(int input){
        if (input <10){
            return Integer.toString(input);
        }
        switch (input){
            case 10:
                return "A";
            case 11:
                return "B";
            case 12:
                return "C";
            case 13:
                return "D";
            case 14:
                return "E";
            case 15:
                return "F";
            default :
                return "";
        }
    }

    public static int h2t(String input){
        int output = 0;
        int i = 0;
        while (i<input.length()){
            output += AEreturn(input.substring(i,i+1))*Math.pow(16,input.length()-i-1);
            i++;
        }
        return output;
    }

    public static int AEreturn(String input){
        try{
            return Integer.parseInt(input);
        }
        catch(NumberFormatException e){
            switch(input){
                case "A":
                    return 10;
                case "B":
                    return 11;
                case "C":
                    return 12;
                case "D":
                    return 13;
                case "E":
                    return 14;
                case "F":
                    return 15;
                default:
                    System.out.println("Some thing wrong!");
                    return 0;
            }
        }
    }
}

看到熟悉的main了嗎?
Java整體結構而言跟C#很像
(或者該說C#跟Java很像,畢竟當年Microsoft就是模仿Java才推出C#的)

先執行

javac convert.java

之後會產生convert.class檔,這個檔案就是給java虛擬機的執行檔
然後就可以用

java convert

來執行你的程式了

JAVA的結構

跟C#相比他不是使用namespace當作最大的結構體,
你可以把他當成用檔名做區分,所以當初才會要求你使用convert.java當作檔名
因為檔名必須跟class的名稱相同

public class convert { //這裡

如果兩者不符可是執行不起來的喔

其他的部份都跟C#一樣就不多做介紹拉,有興趣的人可以去翻C#的結構,看完再回來

輸入與輸出

System.out.println("Tell me what you want to do:");
System.out.println("(1)T to H (2)H to T");
Scanner scanner = new Scanner(System.in);
String choose = scanner.nextLine();

System.out.println

這個是Java的輸出語句,ln代表輸出後會換行的意思,如果只是單純的print將會輸出後不換行
你可以將ln拿掉後再次執行看看
(記得要先javac再次編譯喔,不然你只會將原本就編譯好的程式再次拿去執行)

輸入就比較有趣了
要先將Scanner import進來

import java.util.Scanner;

接著將Scanner實體化

Scanner scanner = new Scanner(System.in);

什麼是實體化?

意思就是我們會宣告一個Scanner的實例,
還記得我們剛才有import Scanner嗎?
這時我們只有將Scanner的藍圖給引用進來而已,要真正使用Scanner必須要將他製造出來

還記得我們之前怎麼在C#宣告String的嗎?

String number = Console.ReadLine();

其實也是在做類似的事情,使用String這張藍圖製造一個叫做number的字串
這個步驟就是實體化

實體化之後就可以使用這個scanner了

String choose = scanner.nextLine();

scanner將會掃描我們的輸入並丟出來到choose內

這邊聽不懂也沒關係,之後我們會有講解物件的文章,到時候會有更詳細的解釋

邏輯判斷 switch

switch(choose) { 
    case "1": 
        System.out.println("Please enter the number:");
        String input = scanner.nextLine();
        System.out.println(t2h(input));
        break;
    case "2": 
        System.out.println("Please enter the number:");
        String hex = scanner.nextLine();
        System.out.println(h2t(hex));
        break; 
    default: 
        System.out.println("輸入錯誤"); 
}

switch的用法基本上跟C#差不多,主要的差別在於java會將 { 放在switch的同一行,而C#會再開一行給他

方法

Java的方法格式為

方法形式 回傳值型別 方法名稱(參數型別 參數名稱)
public static String t2h(String input){
    int number = Integer.parseInt(input) ;
    for(int i = 0; i < 16; i++) {
        for (int j = 0; j <16; j++){
            for (int k = 0; k <16; k++){
                if (Math.pow(16,2)*i+Math.pow(16,1)*j+Math.pow(16,0)*k == number){
                    return returnAE(i)+returnAE(j)+returnAE(k);
                }
            }
        }
    }
    return "";
}

好像多了一個public?

沒錯,不過這個我們保留到物件導向再提

還多了一個return

當執行到return時表示立刻結束當前的程式並回傳後面的值

這次我們改變作法讓程式找到 i j k 時就回傳,不用等到所有迴圈結束,
因此既然有return值的話我們就需要在宣告方法時告訴java我們要回傳的型別(String)
加在方法名稱的前面

轉型

跟C#及python一樣,都是屬於強型別的語言,因此輸入值必須要經過轉型後才能跟數字做比較

int number = Integer.parseInt(input) ;

java內的轉型跟C#很像

迴圈 for

迴圈的部份跟C#的差別在於 { 的位置
C#習慣會獨立一行,而java則跟for同一行

for(int i = 0; i < 16; i++) {

其餘部份都差不多

邏輯判斷 if

基本上跟C#一樣,跳過

java的return

找到符合十六進位的 i, j, k, 後就可以return了
java裡面對字串相加(就是把字串接在一起的意思)只需要使用 +
於是我們有了

return returnAE(i)+returnAE(j)+returnAE(k);

記得喔,只要方法宣告時有回傳值(就是我們指定型別的那個),就一定要return
因此在迴圈結束後如果還是沒找到的話就回傳空字串""吧

讓我們繼續看returnAE的程式吧

public static String returnAE(int input){
    if (input <10){
        return Integer.toString(input);
    }
    switch (input){
        case 10:
            return "A";
        case 11:
            return "B";
        case 12:
            return "C";
        case 13:
            return "D";
        case 14:
            return "E";
        case 15:
            return "F";
        default :
            return "";
    }
}

注意到這一行

Integer.toString(input);

這是將數字轉成字串的方法,有發現跟字串轉數字的方法長得很像嗎?

Integer.parseInt(input) ;

相較之下的C#

Int64 num = Int64.Parse(number); //字串轉形成數字
number.ToString(); //數字轉形成字串

C#會這麼做的原因是把ToString()當作是int的方法,因為數字是一定可以轉型成字串的
但反之則不一定,因此字串不會有轉型成int的方法,只能用Int自己提供的方法來轉型

而java則是都取用int提供的方法來轉型

如果聽不懂也沒關係,之後提到物件時會再拿出來講

來看看將十六進位轉成十進位的方法 h2t 吧

public static int h2t(String input){
    int output = 0;
    int i = 0;
    while (i<input.length()){
        output += AEreturn(input.substring(i,i+1))*Math.pow(16,input.length()-i-1);
        i++;
    }
    return output;
}

基本上跟C#一模一樣,差別只在於while的{

java中取得字串長度的方法是使用字串.length()

這邊我把input.length拿到while裡面了,希望大家還是看得懂(有沒有使用變數的差異)

Java的錯誤處理

public static int AEreturn(String input){
    try{
        return Integer.parseInt(input);
    }
    catch(NumberFormatException e){
        switch(input){
            case "A":
                return 10;
            case "B":
                return 11;
            case "C":
                return 12;
            case "D":
                return 13;
            case "E":
                return 14;
            case "F":
                return 15;
            default:
                System.out.println("Some thing wrong!");
                return 0;
        }
    }
}

結構跟C#基本上一樣,但是要注意一點

catch(NumberFormatException e)

JAVA必須指定要抓住的錯誤類型(其實C#也建議這麼做,但是你不指定的話就是全抓)
這邊我指定如果是數字格式錯誤的話就把錯誤抓起來執行內部的程式

還有其他種類的錯誤,不過就交由大家自己去研究拉

小結

來複習今天學的語法吧

  • 程式結構
    • 除了namespace以外都跟C#類似
    • 行尾一樣需要;
  • 印出/讀取
    • 輸出使用println
    • 輸入使用Scanner 必須經過實例化後才能使用
  • 邏輯控制
    • switch,基本上跟C#類似
    • if ,基本上跟C#類似
  • 迴圈控制
    • for,基本上跟C#類似
    • while ,基本上跟C#類似
  • 方法定義的方式跟C#類似
    • 靜態型別的語言,必須事先定義好輸入值與輸出值的型別
  • 轉型
    • 數值相關轉型一律使用 Integer.
  • 異常處理,基本上跟C#類似

如果有學過C#的人應該會覺得JAVA還蠻好學的,語法上基本上都類似

但是因為算是從C++簡化而來的版本,因此還是看得到一些叫早期語言才會有的寫法
(比方說Scanner要先實例化才能夠使用)
基本上比較晚期的語言(比方說golang)就已經看不太到這種作法了

明天我們來介紹跟JAVA的關係就如同牛跟牛蒡關係的javascript


上一篇
python 簡單又不失強大
下一篇
javascript 如果你只想學一種語言就搞定前後端,那就選他吧
系列文
你會十五種程式語言?不,我會十五種HelloWorld.為了避免這種狀況,因此寫了這篇:淺入淺出十五種程式語言30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
skycover
iT邦新手 4 級 ‧ 2020-09-07 22:15:53

如果有任何寫不清楚或是觀念沒有很明白的話請留言告知我
會盡快補上

如果有任何寫錯的地方也麻煩留言告知我
會盡快修正

感謝各位

0
ultrahsin
iT邦新手 5 級 ‧ 2021-05-22 17:21:02

分享安裝java的細節:

  1. 本來只安裝java jre,bash 卻沒有javac的指令。安裝java jdk後再重開bash後就通了。java jdk載點
  2. 跑javac遇到編碼問題,可參考文章

我要留言

立即登入留言