軟體: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等辭彙,如果有,又打了對勾,那就取消一下試試嘛,反正大不了記住位置,一會兒再勾回來嘛。)
把壓縮空的中間軟體包取消勾選,就可以看到可以正常建立空白包的子包了。
項目結構如下圖:
- 看以下代碼須知:本人是個菜鳥,才學完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().
}
}
附圖:
//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;
}
}
//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 + "客戶不存在");
}
}
}
//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("--------------添加完成-----------");
}
}
//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;
}
}
#########################################################################
(明天,後天,大後天的任務是把這個項目從頭徹底的自己寫出來,徹底理解。)
末尾:(和這個項目無關的代碼,僅僅為了展示構造器的一些性質,值得深思。還是沒讀懂Java核心技術捲一第11版中文版P108頁的警告)
原書內容:警告:請註意,不要再構造器中定義與實例欄位同名的局部變數。例如下麵的構造器將不會設置salary。
public Employee(String n,double s,...){
String name = n;//ERROR
double salary = s;//ERROR
}
這個構造器聲明瞭局部變數name和salary。這些變數只能在構造器內部訪問。這些變數會遮蔽(shadow)同名的實例欄位。有些程式員偶爾會不假思索地寫出這類代碼,因為他們的手指會不自覺地增加數據類型。這種錯誤很難檢查出來,因此,必須註意在所有的方法中都不要使用與實例欄位同名的變數。
他到底是什麼意思呢?是在說構造器內的變數,具有局部性,出了這個構造器,這個變數就不被承認?
實例欄位不就指的是成員變數嗎?
他是在說我下麵圖片中演示的測試1,2那樣?
好奇怪啊,是這個版本的翻譯不行嗎?有機會找來原著看看,現在不都把名字和實例欄位設置成一樣的嗎?然後用this區分哪個是實例欄位,哪個是局部欄位嘛?為什麼書中說不建議?好奇怪?
- 關於構造器,還不太清楚的可以看以下的文章。(其他人寫的,我覺得初學者應該瞭解構造器的具體用處。下麵的都是引用其他人的文章,希望會對你的理解有點幫助。)
https://www.jb51.net/article/266354.htm - 關於數組是值傳遞還是引用傳遞的問題: 答案是引用傳遞,即是賦值的時候,其實是地址傳遞過去了。
- 關於this.all = new Customer[2];這裡不懂的,可以參考這個鏈接:
https://blog.csdn.net/qq_46423166/article/details/128588295 - 關於Arrays.copyOf(this.all, this.total)
- 關於System.arraycopy的使用方法詳解:
https://blog.csdn.net/wenzhi20102321/article/details/78444158 - 學習各種語言的寶藏網站:菜鳥教程,鏈接如下:
https://www.runoob.com/