Java練手項目(尚矽谷的),不涉及框架,資料庫等。

来源:https://www.cnblogs.com/cai-niao-jin-hua-shi-9-21/archive/2023/05/04/17370527.html
-Advertisement-
Play Games

軟體:idea 我是先建立了一個空白的項目,自己創建的src包和其下麵的包。 **問題一:**建立包之後發現格式為src.com.tjp.bean 沒辦法建立其他與bean同級的service test utils view 等。只允許繼續建立bean的子包。 解決: 這是因為idea自動會摺疊空白 ...


軟體:idea
我是先建立了一個空白的項目,自己創建的src包和其下麵的包。
問題一:建立包之後發現格式為src.com.tjp.bean 沒辦法建立其他與bean同級的service test utils view 等。只允許繼續建立bean的子包。
解決: 這是因為idea自動會摺疊空白包。(不同版本的idea可能和我的位置不太一樣,但是都在那個齒輪里,第一步都先點擊那個齒輪,看看裡面有沒有提到fold empty等辭彙,如果有,又打了對勾,那就取消一下試試嘛,反正大不了記住位置,一會兒再勾回來嘛。)
image


把壓縮空的中間軟體包取消勾選,就可以看到可以正常建立空白包的子包了。
項目結構如下圖:

  • 看以下代碼須知:本人是個菜鳥,才學完Java的語法知識和麵向對象相關的知識,掌握的也不是很好,下麵代碼中的註釋,都是我根據自己的理解,添加的註釋,如果有錯的或者不恰當的地方,希望各位大佬可以不吝賜教。謝謝!
  • 裡面的代碼是尚矽谷的代碼。因為尚矽谷的代碼是用eclipse寫的,我本來嘗試了一下eclipse代碼包轉idea項目,但是失敗了,不過好在這個項目還不涉及框架和資料庫什麼的,因此我就仿照尚矽谷的代碼結構,建立了包,和類,把他的代碼複製粘貼到我的類中,運行起來沒有任何問題,反正這次的目的主要是研究,以及熟練掌握一下代碼語法。多練,多動手嘛!
  • 正常應該先看bean下的customer類,但是我覺得代碼太多了,我喜歡從代碼少的開始看,你們就隨意啦!
//Test類代碼:
package src.com.tjp.test;
//先聲明本類所在的位置。嘿我在這裡!
import src.com.tjp.view.CustomerView;
//導入view包下的CustomerView類,因為下麵要創建它的對象,調用它的方法,所以需要把這個類先導入到這個類裡面。
public class Test {
//Test類開始
    public Test(){
    }
//Test無參構造器。

    public static void main(String[] args) {
// Test類入口,主函數。
        CustomerView view = new CustomerView();
// 創建了CustomerView類的對象view.
        view.menu();
// 用創建的對象view,調用CustomerView類的方法menu().
    }
}

附圖:
image

//Customer類代碼:
package src.com.tjp.bean;
//先寫明本類所在的位置.講個好玩的:你是誰啊?我爸爸是bean,爺爺是tjp,太爺爺是com,太太爺爺是src.我是這一支的人,現在你知道我是誰了吧?
public class Customer {
//本類開始。
    private String name;
//一般標準bean都是把屬性,定義為私有的,然後其他類想要這個屬性的值,就通過set get方法獲得。
// 私有化屬性name String類型的.
    private char gender;
// gender:性別的意思。
    private int age;
// 屬性,成員變數,實例欄位是一個意思.
// 欄位是屬於類的,它是會用public、private等關鍵字修飾的。
    private String phone;
    private String email;
    public Customer(){
// 創建一個Customer無參構造器。
    }
    public Customer(String name, char gender, int age, String phone, String email){
//  創建一個Customer有參構造器,形參是name,gender,age,phone,email.
        this.name = name;
//  this.name 為構造器外面,本類最開始定義的成員變數,
//  構造器又可以叫做構造方法,構造器可以被看做是一種特殊的方法。構造器用於構造該類的實例,也就是對象。
//  構造器格式:[修飾符] 類名 (形參列表){//n條語句}
//  ##構造器與方法的區別:
//  1.構造器的名字必須與定義它的類名完全相同,沒有返回類型,甚至連void也沒有。
//  2.構造器的調用是在創建一個對象時使用new操作進行的。構造方法的作用是初始化對象。
//  3.不能被static、final、synchronized、abstract和native修飾。構造方法不能被子類繼承。
//  4.構造方法可以被重載。沒有參數的構造方法稱為預設構造方法,與一般的方法一樣,構造方法可以進行任何活動,但是經常將他設計為進行各種初始化活動,比如初始化對象的屬性。
//  5.每個類可以有一個以上的構造器.
//  6.構造器可以有0個,1個,或多個參數.
//  7.構造器總是伴隨著new操作符一起調用.
//  8.構造器與其他方法有一個重要的不同.構造器總是結合new運算符來調用.不能對一個已經存在的對象調用構造器來達到重新設置實例欄位的目的.
//  例子:jams.Employee("James Bond",250000,1950,1,1)//ERROR
//  例子: new Employee("Jams Bond",100000,1950,1,1)//CORRECT
//  #方法:
//  1.方法包含於類或對象中,方法在程式中被創建,在其他地方被引用.
//  2.命名規則:方法的名字的第一個單詞應以小寫字母作為開頭,後面的單詞則用大寫字母開頭寫,不使用連接符。例如:addPerson。
//  3.命名規則:下劃線可能出現在 JUnit 測試方法名稱中用以分隔名稱的邏輯組件。一個典型的模式是:test<MethodUnderTest>_<state>,例如 testPop_emptyStack。
//  4.修飾符 返回值類型 方法名(參數類型 參數名){方法體 return 返回值;}沒有返回值的時候,用void,而不可以像構造器那樣,不去寫.
//  5.調用一個方法時候需要提供參數,你必須按照參數列表指定的順序提供。
//  *******************************************
//  成員變數和局部變數的區別:
//  1.在類中位置不同:成員變數:在類中方法外。局部變數:在方法定義中或者方法聲明上。
//  2.在記憶體中的位置不同:成員變數:在堆記憶體。  局部變數:在棧記憶體。
//  3.生命周期不同:成員變數:隨著對象的創建而存在,隨著對象的消失而消失。 局部變數:隨著方法的調用而存在,隨著方法的調用完畢而消失。
//  4.初始化值不同:成員變數:有預設值初始化。局部變數:沒有預設值初始化,必須定義,賦值,然後才能使用。
//  5.註意事項:局部變數名稱可以和成員變數名稱一樣(用this區分),在方法中使用的時候,採用的是就近原則。
//  用this修飾的變數,為成員變數,沒有用this修飾的變數,根據就近原則,為局部變數,即構造器里聲明的變數,成員變數和局部變數名字可以不同,
//  但是都用的相同的名字,一方面可能是見名知意思,另一方面可能是比較懶,不想起其他名字,防止混亂?僅僅只是我自己的理解,不知對不對。
        this.gender = gender;
        this.age = age;
        this.phone = phone;
        this.email = email;
    }
//  以下是set get方法.用ALT+Insert快捷鍵快速生成set, get方法.也可以滑鼠右鍵->點擊生成->getter Setter
//  如果按了快捷鍵發現沒有彈窗,你的電腦又恰好是聯想小新,可以試試,Fn+Esc.按下去發現Esc鍵亮起,說明上面一排從F1~F12~Insert, PrtSc都恢復了正常功能.
//  如果你還指望用F3調節音量大小,那我建議你,記得寫完代碼後,再按Fn+Esc,讓Esc的燈光再次熄滅.
//  這回可以再試試剛纔的快捷鍵了,如果還是不行,那就百度一下吧.

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

    public void setName(String name) {
        this.name = name;
    }
    public char getGender(){
        return this.gender;
    }
    public void setGender(char gender){
        this.gender = gender;
    }
    public int getAge(){

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

        this.age = age;
    }
    public String getPhone(){

        return this.phone;
    }
    public void setPhone(String phone){

        this.phone = phone;
    }
    public String getEmail(){

        return this.email;
    }
    public void setEmail(String email){
        this.email = email;
    }
//  CustomerView類中list方法會調用這個getInfo方法,用於輸出.
    public String getInfo(){
        return this.name + "\t" + this.gender + "\t" + this.age + "\t" + this.email;
    }
}

image
image
image
image
image

//CustomerService代碼:
package src.com.tjp.service;
//聲明本類所在的位置。
import src.com.tjp.bean.Customer;
//導入Customer類。
import java.util.Arrays;
//導入Java自帶的util包下的Arrays類,如果不導入這個類,下麵用arrays的時候,就會報錯。
public class CustomerService {
//  本類開始。
    private Customer[] all;
//  這個我也不太確定,應該是私有化定義一個Customer類類型的數組,all.
    private int total;
//  私有化定義一個int類型的成員變數total
    public CustomerService() {
        this.all = new Customer[2];
    }
//  本類的無參構造器,創造一個Customer類類型的兩個長度的數組,並把這個數組地址賦值給ALL數組。(數組是引用類型,應該是地址傳遞)
    public CustomerService(int initSize) {
        this.all = new Customer[initSize];
    }
//  本類的有一個形參的構造器,initSize是規定幾個可以輸入的,例如編號,性別,等的最小輸入範圍,但是為什麼這麼寫,不太清楚,這裡不太理解。
    public void addCustomer(Customer c) {
//  本類的一個無返回值的公有的addCustomer方法,形參有一個Customer類型的 c.
        if (this.total >= this.all.length) {
            System.out.println("數組已滿");
        } else {
            this.all[this.total++] = c;
        }
    }

    public Customer[] getAll() {
        return (Customer[]) Arrays.copyOf(this.all, this.total);
    }
//  返回值類型是Customer[]的方法?應該是這個意思?
    public void removeById(int id) {
//  公有的,沒有返回值的,一個形參的removeById方法。
//  從CustomerView類中,刪除用戶方法中,調用此方法,從輸入控制台傳入要刪除的id號。
//  把id-1為了讓它和數組下標對應,並查找擁有該數組下標的,是否存在。
//  該死的,用這麼多方法。頭大。

        int index = id - 1;
        if (index >= 0 && index < this.total) {
            System.arraycopy(this.all, index + 1, this.all, index, this.total - index - 1);
//                           原數組,    源數組要複製的起始位置,目的數組,目的數組放置的起始位置,複製的長度。
            this.all[--this.total] = null;
//  居然還可以這樣寫,妙啊。
        } else {
            System.out.println(id + "對應的客戶不存在");
        }
    }

//  查看輸入的id,是否存在對應的客戶。
    public Customer getById(int id) {
        int index = id - 1;
        if (index >= 0 && index < this.total) {
            return this.all[index];
        } else {
            System.out.println(id + "客戶不存在");
            return null;
        }
    }
//  修改用戶,查看需要修改的用戶是否存在。
    public void replace(int id, Customer newCustomer) {
        int index = id - 1;
        if (index >= 0 && index < this.total) {
            this.all[index] = newCustomer;
        } else {
            System.out.println(id + "客戶不存在");
        }
    }
}

image
image
image

//CustomerView類的代碼:
package src.com.tjp.view;

import src.com.tjp.bean.Customer;
import src.com.tjp.service.CustomerService;
import src.com.tjp.utils.CMUtility;
public class CustomerView {
    private CustomerService cs = new CustomerService();
//    這個私有化創建對象的做法值得深思。
    public CustomerView(){
    }
    public void menu(){
        while(true) {
            System.out.println("----------客戶信息管理軟體----------");
            System.out.println("\t\t\t1. 添加客戶");
            System.out.println("\t\t\t2. 修改客戶");
            System.out.println("\t\t\t3. 刪除客戶");
            System.out.println("\t\t\t4. 客戶列表");
            System.out.println("\t\t\t5. 退   出");
            System.out.println("----------請選擇(1~5):");
            char select = CMUtility.readMenuSelection();

            switch(select){
                case '1':
                    this.add();
                    break;
                case '2':
                    this.update();
                    break;
                case '3':
                    this.delete();
                    break;
                case '4':
                    this.list();
                    break;
                case '5':
                    System.out.println("確認退出嘛?Y/N");
                    char confirm = CMUtility.readConfirmSelection();

                    if (confirm == 'Y') {
                        return;
                    }
            }
        }
    }
    private void list(){
        Customer[] all = this.cs.getAll();
        System.out.println("-------------客戶列表--------------");
        System.out.println("編號\t姓名\t性別\t年齡\t電話\t郵箱");
        for(int i = 0;i < all.length; ++i) {
            System.out.println((i + 1) + "\t" + all[i].getInfo());
        }
        System.out.println("-------------客戶列表完成----------");
    }
    private void delete(){
        System.out.println("-------------刪除客戶--------------");
        System.out.println("請選擇待刪除客戶編號(-1退出):");
        int id = CMUtility.readInt();
        if (id != -1) {
            System.out.println("確認是否刪除(Y/N):");
            char confirm = CMUtility.readConfirmSelection();
            if (confirm != 'N'){
                this.cs.removeById(id);
                System.out.println("-------------刪除完成-----------");
            }
        }

    }
    private void update(){
        System.out.println("--------------修改客戶------------");
        System.out.println("請選擇待修改客戶編號(-1退出):");
        int id = CMUtility.readInt();
        if(id != -1) {
            Customer old = this.cs.getById(id);
            System.out.println("姓名(" + old.getName() + "): ");
            String name = CMUtility.readString(20, old.getName());
            System.out.println("性別(" + old.getGender() + "): ");
            char gender = CMUtility.readChar(old.getGender());
            System.out.println("年齡(" + old.getAge() + "): ");
            int age = CMUtility.readInt(old.getAge());
            System.out.println("電話(" + old.getPhone() + "): ");
            String phone = CMUtility.readString(11, old.getPhone());
            System.out.println("郵箱(" + old.getEmail() + "): ");
            String email = CMUtility.readString(32, old.getEmail());
            Customer newCustomer = new Customer(name, gender, age, phone, email);
            this.cs.replace(id, newCustomer);
            System.out.println("--------------修改完成------------");
        }

    }
    private void add(){
        System.out.println("--------------添加客戶-----------");
        System.out.println("姓名: ");
        String name = CMUtility.readString(20);
        System.out.println("性別: ");
        char gender = CMUtility.readChar();
        System.out.println("年齡: ");
        int age = CMUtility.readInt();
        System.out.println("電話: ");
        String phone = CMUtility.readString(11);
        System.out.println("郵箱: ");
        String email = CMUtility.readString(32);
        Customer c = new Customer(name, gender, age, phone, email);
        this.cs.addCustomer(c);
        System.out.println("--------------添加完成-----------");
    }
}

image
image
image
image

//CMUtility類的代碼:
package src.com.tjp.utils;

import java.util.Scanner;
public class CMUtility {
    private static Scanner scanner;
    static {
        scanner = new Scanner(System.in);
    }
    public CMUtility() {
    }
    public static char readMenuSelection() {
        while(true) {
            String str = readKeyBoard(1, false);
            char c = str.charAt(0);
            if (c == '1' || c == '2' || c == '3' || c == '4' || c == '5') {
                return c;
            }

            System.out.print("選擇錯誤,請重新輸入:");
        }
    }
    public static char readChar() {
        String str = readKeyBoard(1, false);
        return str.charAt(0);
    }

    public static char readChar(char defaultValue) {
        String str = readKeyBoard(1, true);
        return str.length() == 0 ? defaultValue : str.charAt(0);
    }

    public static int readInt() {
        while(true) {
            String str = readKeyBoard(2, false);

            try {
                int n = Integer.parseInt(str);
                return n;
            } catch (NumberFormatException var3) {
                System.out.print("數字輸入錯誤,請重新輸入:");
            }
        }
    }

    public static int readInt(int defaultValue) {
        while(true) {
            String str = readKeyBoard(2, true);
            if (str.equals("")) {
                return defaultValue;
            }

            try {
                int n = Integer.parseInt(str);
                return n;
            } catch (NumberFormatException var4) {
                System.out.print("數字輸入錯誤,請重新輸入:");
            }
        }
    }

    public static String readString(int limit) {
        return readKeyBoard(limit, false);
    }

    public static String readString(int limit, String defaultValue) {
        String str = readKeyBoard(limit, true);
        return str.equals("") ? defaultValue : str;
    }

    public static char readConfirmSelection() {
        while(true) {
            String str = readKeyBoard(1, false).toUpperCase();
            char c = str.charAt(0);
            if (c == 'Y' || c == 'N') {
                return c;
            }

            System.out.print("選擇錯誤,請重新輸入:");
        }
    }

    private static String readKeyBoard(int limit, boolean blankReturn) {
        String line = "";

        while(scanner.hasNextLine()) {
            line = scanner.nextLine();
            if (line.length() == 0) {
                if (blankReturn) {
                    return line;
                }
            } else {
                if (line.length() >= 1 && line.length() <= limit) {
                    break;
                }

                System.out.print("輸入長度(不大於" + limit + ")錯誤,請重新輸入:");
            }
        }

        return line;
    }
}

image
image
image
image

#########################################################################
(明天,後天,大後天的任務是把這個項目從頭徹底的自己寫出來,徹底理解。)
末尾:(和這個項目無關的代碼,僅僅為了展示構造器的一些性質,值得深思。還是沒讀懂Java核心技術捲一第11版中文版P108頁的警告)

原書內容:警告:請註意,不要再構造器中定義與實例欄位同名的局部變數。例如下麵的構造器將不會設置salary。
public Employee(String n,double s,...){
String name = n;//ERROR
double salary = s;//ERROR
}
這個構造器聲明瞭局部變數name和salary。這些變數只能在構造器內部訪問。這些變數會遮蔽(shadow)同名的實例欄位。有些程式員偶爾會不假思索地寫出這類代碼,因為他們的手指會不自覺地增加數據類型。這種錯誤很難檢查出來,因此,必須註意在所有的方法中都不要使用與實例欄位同名的變數。

他到底是什麼意思呢?是在說構造器內的變數,具有局部性,出了這個構造器,這個變數就不被承認?
實例欄位不就指的是成員變數嗎?
他是在說我下麵圖片中演示的測試1,2那樣?
好奇怪啊,是這個版本的翻譯不行嗎?有機會找來原著看看,現在不都把名字和實例欄位設置成一樣的嗎?然後用this區分哪個是實例欄位,哪個是局部欄位嘛?為什麼書中說不建議?好奇怪?
image


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • (DQL語言) 一、前言 上一節中我們說了DML 數據操作語言,這一篇到了DQL語言,DQL語言就是我們常說的select 語句。 它是從一個表或多個表中根據各種條件,檢索出我們想要的數據集。 DQL語句算是我們工作中最長用也是最複雜的SQL語句了。 二、基礎查詢 2.1 語法 -- ① 查詢欄位 ...
  • 本文首發於公眾號:Hunter後端 原文鏈接:Django筆記三十五之admin後臺界面介紹 這一篇介紹一下 Django 的後臺界面使用。 Django 自帶了一套後臺管理界面,可用於我們直接操作資料庫數據,本篇筆記目錄如下: 創建後臺賬號以及登錄操作 註冊後臺顯示的數據表 列表欄位的顯示操作 字 ...
  • 我的開源項目消息推送平臺Austin終於要上線了,迎來線上演示的第一版! 🔥項目線上演示地址:http://139.9.73.20:3000/ 消息推送平臺🔥推送下發【郵件】【簡訊】【微信服務號】【微信小程式】【企業微信】【釘釘】等消息類型。 https://gitee.com/zhongfuc ...
  • 為解決傳統高校科技管理工作中存在的信息失誤率高、傳遞速度緩慢等一系列缺陷,設計開發了基於Java EE的高校科技管理系統,為高校科技管理工作提供了極大的便利。同時還可以用於大創項目,政府類的創新類項目,科研類項目申報管理系統平臺,互聯網+項目申報系統。 ...
  • 雖然現在IDE很強大又很智能,但是平常隨意寫點練手的代碼的時候,直接在命令行中使用vim和java命令更為方便快捷,可以做到無滑鼠純鍵盤的操作。 首先保證將java相關指令添加到了環境變數中; 1.編譯class文件: javac -d ./ Test.java 編譯好的class文件會放置到環境當 ...
  • Java讀取資料庫表(二) application.properties db.driver.name=com.mysql.cj.jdbc.Driver db.url=jdbc:mysql://localhost:3306/easycrud?useUnicode=true&characterEnco ...
  • 在之前的文章中,我們已經對 `bean` 的準備工作進行了講解,包括 `bean` 定義和 `FactoryBean` 判斷等。在這個基礎上,我們可以更加深入地理解 `getBean` 方法的實現邏輯,併在後續的學習中更好地掌握`createBean` 方法的實現細節。 ...
  • 背景說明 最近在做財務相關的系統,對賬單核銷預付款從技術角度來看就是將兩個數組進行合併 對賬單核銷預付款前提條件: 對賬單總金額必須等於未核銷金額 數據示例 對賬單數據 | 單號 | 金額 | | | | | B0001 | 100 | | B0002 | 80 | | B0003 | 120 | ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...