文章目錄
- 面向物件思想
- 概述
- 面向程序與面向物件的區別
- 舉例
- 區別
- 代碼展示
- 特點
- 面向物件三條主線
- 類和物件
- 什么是類
- 什么是物件
- 類與物件的關系
- 類的定義
- 事物與類的對比
- 類的定義格式
- 物件的使用
- 使用步驟
- 代碼舉例
- 例一
- 例二
- 成員變數默認值
- 物件記憶體圖
- `jvm`記憶體劃分圖
- 一個物件的記憶體圖
- 兩個物件參考指向不同物件空間的記憶體圖
- 兩個物件參考指向同一物件空間的記憶體圖
- 物件在方法中的使用
- 使用物件型別作為方法的引數
- 使用物件型別作為方法的回傳值
- 成員變數和區域變數的區別
- 練習
- 方法
- 方法多載
- 概念
- 特點
- 可變形參的方法
- 格式
- 使用
- **方法引數的值傳遞機制**
- 練習
- 練習1
- 練習2
- 遞回方法
- 三大特征之封裝
- 封裝概述
- 概述
- 原則
- 體現
- private關鍵字
- 使用說明
- 間接訪問
- Setter方法
- Getter方法
- 練習
- this關鍵字
- **誰呼叫的方法,this就指向誰,**
- this 呼叫構造器
- 構造器
- 構造器的定義格式
- 注意事項
- 標準代碼——JavaBean
- 舉例
- static
- 修飾屬性
- 使用場景
- static記憶體圖
- 修飾方法
- 使用場景
- 修飾代碼塊
- 靜態代碼塊
面向物件思想
概述
Java語言是一種面向物件的程式設計語言,而面向物件思想是一種程式設計思想,我們在面向物件思想的指引下,使用Java語言去設計、開發計算機程式, 這里的物件泛指現實中一切事物,每種事物都具備自己的屬性和行為,面向物件思想就是在計算機程式設計程序中,參照現實中事物,將事物的屬性特征、行為特征抽象出來,描述成計算機事件的設計思想, 它區別于面向程序思想,強調的是通過呼叫物件的行為來實作功能,而不是自己一步一步的去操作實作,
面向程序與面向物件的區別
面向程序:當需要實作一個功能時,每一個具體的步驟都要親歷親為,詳細處理每一個細節,
面向物件:當需要實作一個功能時,不關心具體的步驟,而是找一個已經具有該功能的人,來幫我們做事,
舉例
洗衣服:
面向程序:把衣服脫下來–>找一個盆–>放點洗衣粉–>加點水–>浸泡10分鐘–>揉一揉–>清洗衣服–>擰干–>晾起來
面向物件:把衣服脫下來–>打開全自動洗衣機–>扔衣服–>按鈕–>晾起來
區別
面向程序:強調步驟,
面向物件:強調物件,這里的物件就是洗衣機,
代碼展示
public class Demo01PrintArray {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
// 要求列印格式為:[1, 2, 3, 4, 5]
// 面向程序實作
System.out.print("[");
for(int i = 0; i < arr.length; i++){
if(i < arr.length - 1) {
System.out.print(arr[i] + ", ");
} else {
System.out.println(arr[i] + "]");
} // 需要關注功能實作的每一個細節
}
System.out.println("===============");
// 面向物件實作
System.out.println(Arrays.(arr));
// 不需要關注功能實作的每一個細節,只需要呼叫具有這個功能的方法即可,
//Arrays.toString()
//JDK提供的Arrays類中的toString() 方法
//Arrays.toString() 可以將陣列轉換成字串格式
}
}

特點
面向物件思想是一種更符合我們思考習慣的思想,它可以將復雜的事情簡單化,并將我們從執行者變成了指揮者,面向物件的語言中,包含了三大基本特征,即封裝、繼承和多型,
面向物件三條主線
- 類及類的成員:屬性(成員變數)、成員方法、構造器、代碼塊、內部類,
- 面向物件三大特性:封裝、繼承、多型,
- 其它關鍵字:this, super, abstract, interface, final, package, import…
類和物件
什么是類
類:是一組相關屬性和行為的集合,可以看成是一類事物的模板,使用事物的屬性特征和行為特征來描述該類事物,
現實中,描述一類事物:
屬性:就是該事物的狀態資訊,
行為:就是該事物能夠做什么,
舉例:小貓,
屬性:名字、體重、年齡、顏色,
行為:走、跑、叫,
什么是物件
物件:是一類事物的具體體現,物件是類的一個實體,必然具備該類事物的屬性和行為,
現實中,一類事物的一個實體:一只小貓,
舉例:一只小貓,
屬性:tom、5kg、2 years、yellow,
行為:溜墻根走、蹦跶的跑、喵喵叫,
類與物件的關系
類是對一類事物的描述,是抽象的,
物件是一類事物的實體,是具體的,
類是物件的模板,物件是類的物體,

類的定義
事物與類的對比
-
現實世界的一類事物:
屬性:事物的狀態資訊,
行為:事物能夠做什么,
-
Java中用class描述事物也是如此:
成員變數:對應事物的屬性
成員方法:對應事物的行為
類的定義格式
public class ClassName {
//成員變數
//成員方法
}
定義類:就是定義類的成員,包括成員變數和成員方法,
成員變數:和以前定義變數幾乎是一樣的,只不過位置發生了改變,在類中,方法外,也叫類的屬性,field,
成員方法:和以前定義方法幾乎是一樣的,只不過把static去掉,static的作用在面向物件后面課程中再詳細講解,
/*
定義一個類,用來模擬"學生",其中就有兩個組成部分:
1、屬性(是什么):
姓名、年齡、性別、...
2、行為(能做什么):
吃飯、睡覺、學習、...
對應到java的類當中:
1、成員變數(屬性):
String name; // 姓名
int age; // 年齡
byte sex; // 性別 0:女,1:男,2:保密
2、成員方法(行為):
public void eat() {} // 吃飯
public void sleep() {} // 睡覺
public void study() {} // 學習
*/
public class Student {
// 成員變數
String name; // 姓名
int age; // 年齡
byte sex; // 性別
// 成員方法
public void eat(){
System.out.println("吃!");
}
public void sleep() {
System.out.println("睡!");
}
public void study() {
System.out.println("學!");
}
}
物件的使用
使用步驟
通常情況下,一個類并不能直接使用,需要根據類創建一個物件,才能使用,具體分為以下三個步驟:
-
導包:指出需要使用的類在什么位置,
如果類同屬于一個包中(同一路徑下),可以省略導包陳述句,
// 導包陳述句
// import packageName.className;
import cn.study.day07.demo03.Demo02Student;
- 創建
// className objName = new className();
Student stu = new Student();
- 使用
使用成員變數
// objName.memberVarName
stu.name = "張三";
使用成員方法
// objName.memberMethName(para,...) para可以是0或多個
stu.eat();
總結:想用誰,就用物件名點兒誰,
代碼舉例
例一
public class Demo02Student {
public static void main(String[] arg){
// 1. 導包
// 需要使用的Student類,和當前所在類同屬一個包下,可以省略導包陳述句,
// 2. 創建
// className objName = new className();
Student stu = new Student();
// 根據Student類創建了一個stu的物件,
//3. 使用其中的成員變數
System.out.println(stu.name); // null
System.out.println(stu.age); // 0
System.out.println(stu.sex); // '\u0000'
// Student類中沒有給成員變數賦值
// 默認值與陣列的規則相同
System.out.println("=====================");
// 改變物件當中的成員變數內容
stu.name = "張三";
stu.age = 18;
stu.sex = '男';
System.out.println(stu.name); // 張三
System.out.println(stu.age); // 18
System.out.println(stu.sex); // 男
System.out.println("=====================");
// 使用成員方法
stu.eat();
stu.sleep();
stu.study();
}
}
例二
/*
定義一個類,用來模擬"手機"事物
屬性:品牌、價格、顏色...
行為:通話、短信...
對應到類當中:
成員變數(屬性)
String brand;
double price;
String color;
成員方法(行為)
public void call(String who) {} // 打電話
public void sendMessage() {} // 群發短信
*/
public class Phone {
//成員變數
String brand; // 品牌
double price; // 價格
String color; // 顏色
//成員方法
public void call(String who){
System.out.println("給" + who + "打電話");
}
public void sendMessage() {
System.out.println("群發短信");
}
}
public class Demo03PhoneOne {
public static void main(String[] args) {
// 根據Phone類,創建一個名為one的物件;
Phone one = new Phone();
System.out.println(one.brand); // null
System.out.println(one.price); // 0.0
System.out.println(one.color); // null
System.out.println("===================");
// 給物件當中的成員重新賦值
one.brand = "小米";
one.price = 998.0;
one.color = "黑色";
System.out.println(one.brand); // 小米
System.out.println(one.price); // 998.0
System.out.println(one.color); // 黑色
System.out.println("===================");
one.call("雷軍");
one.sendMessage();
}
}
成員變數默認值
成員變數如果未賦值,將會有一個默認值,規則如下:
- 整數型別,默認為0;
- 浮點型別,默認為0.0;
- 字符型別,默認為
'\u0000'; - 布爾型別,默認為
false; - 參考型別,默認為
null,
物件記憶體圖
jvm記憶體劃分圖

一個物件的記憶體圖

堆中的成員變數是參考方法區.class中成員變數的資訊創建的,其中的值就保存在堆(Heap)中,
堆中的成員方法保存的是一個地址值,指向了方法區中的成員方法資訊,
進堆疊也叫壓堆疊,先進堆疊的在后進堆疊的下面,后來的壓著先來的,
出堆疊也叫彈堆疊,當方法執行完畢后會立刻從堆疊中銷毀,main方法執行完畢,則程式結束,
先進后出,后進先出,
兩個物件參考指向不同物件空間的記憶體圖
物件名,也叫物件參考

從上圖可以看到,兩個物件在創建時,分別在堆區開辟了不同的記憶體空間,各自保存著本物件的成員變數和成員方法,但是這兩塊堆區記憶體空間同時指向了方法區里同一塊空間,也就是它們的所具有的屬性和功能是完全相同的,不同的是成員變數的值和成員方法呼叫的引數,
這會出現一個問題,每創建一個物件就需要在堆中開辟一塊記憶體空間,但是里面保存的資訊基本相同,因此十分浪費記憶體空間,
兩個物件參考指向同一物件空間的記憶體圖

物件在方法中的使用
使用物件型別作為方法的引數
任何資料型別都能作為方法的引數,
物件參考作為引數傳遞給方法的是物件的地址值,
public class Demo04PassObjParam {
public static void main(String[] args) {
Phone one = new Phone();
one.brand = "小米";
one.price = 998.0;
one.color = "土豪金";
mothod(one); // 傳遞的物件的地址
System.out.println(one);
}
public static void mothod(Phone param){
System.out.println(param);
System.out.println(param.brand); // 蘋果
System.out.println(param.price); // 998.0
System.out.println(param.color); // 土豪金
}
}


使用物件型別作為方法的回傳值
使用物件型別作為方法的回傳值時,回傳的是物件的地址值,
public class Demo05PhoneReturn {
public static void main(String[] args) {
// 用物件型別接識訓傳值
Phone two = getPhone();
System.out.println(two.brand); // 小米
System.out.println(two.price); // 799.0
System.out.println(two.color); // RoseGold
}
public static Phone getPhone() {
Phone one = new Phone();
one.brand = "小米";
one.price = 799.0;
one.color = "RoseGold";
return one;
}
}

成員變數和區域變數的區別
-
定義的位置不一樣
區域變數:在方法的內部
成員變數:在方法的外部,直接寫在類當中,
-
作用域不一樣
區域變數:所在方法中可以使用,出了所在方法就不能使用,
成員變數:整個類全都可以通用,
-
默認值不一樣
區域變數:沒有默認值,要使用,必須先賦值,
成員變數:如果沒有賦值,會有默認值,規則和陣列一樣,
-
記憶體的位置不一樣
區域變數:位于堆疊記憶體,
成員變數:位于堆記憶體,
-
宣告周期不一樣
區域變數:隨著方法進堆疊而創建,隨著方法出堆疊而銷毀,
成員變數:隨著物件創建而創建,隨著物件被垃圾回收而消失,
-
權限修飾符的使用不同,
public、 protected、 預設、 private區域變數:不能使用權限修飾符,
成員變數:可以使用權限修飾符,
public class Demo01VariableDifference {
String name; // 成員變數
public void methodA(){
int num = 20; // 區域變數
System.out.println(num);
}
public void methodB(int param) { //引數就是區域變數
// System.out.println(num); // 錯誤,num是methodA方法中的區域變數,不能在methodB中使用
System.out.println(name); // 成員變數,類中都可以使用
int age; // 區域變數
// System.out.println(age); // 區域變數未賦值不能使用
// 引數在方法呼叫時,必然會被賦值
System.out.println(param); // 這種寫法沒有問題
}
}
練習
創建一個學生類,三個屬性,學號,年級和成績,
創建20個學生類,其中學號從1開始到20結束,年級和成績隨機賦值,
Student類
// Student類
package cn.study.day26.demo05;
public class Student {
private int number = id; // 學號
private int state; // 年級
private int score; // 成績
private static int id = 1; // 自增id
// 無參構造器
public Student() {
++id;
}
// 有參構造器,number和id變數自增,不允許設定
public Student(int state, int score) {
this.state = state;
this.score = score;
}
public String stuInfo() {
String info = "學號:" + this.getNumber() + ", 年級:" +this.getState() + ", 成績:" + this.getScore();
return info;
}
// Getter/Setter
public int getNumber() {
return this.number;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
工具類
// 工具類
package cn.study.day26.demo05;
public class Utility {
// 遍歷列印學生資訊
/**
* @Description 遍歷Student陣列,并列印陣列中學生物件的資訊
* @author Joker
* @param stus 要遍歷的陣列
*/
public static void traverseStu(Student[] stus) {
for (int i = 0; i < stus.length; i++) {
System.out.println(stus[i].stuInfo());
}
}
/**
* @Description 篩選出Student陣列中指定年級學的資訊,并列印,
* @author Joker
* @param state 需要篩選出來的年級
*/
public static void searchStu(Student[] stus, int state) {
for (int i = 0; i < stus.length; i++) {
if (stus[i].getState() == state) {
System.out.println(stus[i].stuInfo());
}
}
}
/**
* @Description 使用冒泡排序演算法,按照成績屬性給Student陣列排序,從小到大,
* @author Joker
* @param stus 要排序的陣列
*/
public static void bubbleSortStus(Student[] stus) {
for (int i = 0; i < stus.length - 1; i++) {
boolean flag = true;
for (int j = 0; j < stus.length - 1 - i; j++) {
if (stus[j].getScore() > stus[j + 1].getScore()) {
Student temp = stus[j];
stus[j] = stus[j + 1];
stus[j + 1] = temp;
flag = false;
}
}
if(flag){
break;
}
}
}
// 按年級快速排序
/**
* Description 使用快速排序演算法,按照年級屬性給Student陣列排序,從小到大
* @author Joker
* @param stus 要排序的陣列
*/
public static void sortStus(Student[] stus){
quickSort(stus, 0, stus.length - 1);
}
// 快速排序
private static void quickSort(Student[] stus, int low, int high) {
int pivot = low;
if(low < high) {
pivot = partition(stus, low, high);
quickSort(stus,low,pivot - 1);
quickSort(stus,pivot + 1, high);
}
}
// 確定基軸值位置
private static int partition(Student[] stus, int low, int high) {
int pivotKey = stus[low].getState();
while(low < high) {
while(low < high && stus[high].getState() >= pivotKey){
high--;
}
swap(stus,low,high);
while (low < high && stus[low].getState() <= pivotKey){
low++;
}
swap(stus,low,high);
}
return low;
}
// 交換兩個物件參考
private static void swap(Student[] stus, int low, int high) {
Student temp = stus[low];
stus[low] = stus[high];
stus[high] = temp;
}
}
測驗類
// 測驗類
package cn.study.day26.demo05;
public class StudentTestDrive {
public static void main(String[] args) {
Student[] stus = new Student[20];
for (int i = 0; i < stus.length; i++) {
stus[i] = new Student();
// stata = [1,6]
// score = [0,100]
// 亂數計算公式[a,b]
// Math.random * (b - a + 1) * a;
int state = (int) (Math.random() * (6 - 1 + 1) + 1);
int score = (int) (Math.random() * (100 + 1));
stus[i].setState(state);
stus[i].setScore(score);
}
// 按年級篩選學生
System.out.println("==========按年級篩選==========");
Utility.searchStu(stus,3);
// 按成績冒泡排序
System.out.println("==========按成績排序==========");
Utility.bubbleSortStus(stus);
Utility.traverseStu(stus); // 遍歷列印學生資訊
// 按年級快速排序
System.out.println("==========按年級排序==========");
Utility.sortStus(stus);
Utility.traverseStu(stus); // 遍歷列印學生資訊
}
}
方法
方法多載
概念
在同一個類中,允許存在一個以上的同名方法,只要它們的引數個數、引數型別或者引數順序不同即可,
特點
與回傳值型別無關,只看引數串列,且引數串列必須不同,(引數個數、引數型別或引數順序),呼叫時,可以根據傳傳遞的實參型別、個數、順序來呼叫對應的方法,
可變形參的方法
JavaSE5.0 中提供了VarArgs(variable number of arguments) 機制,允許直接定義和能多個實參相匹配的形參,從而,可以用一種更簡單的方式,來傳遞個數可變的實參,
格式
權限修飾符 回傳值型別 方法名(資料型別 ... 引數名) {}
使用
-
當呼叫可變個數形參的方法時,傳入的引數個數可以是
0,1,2... 多個 -
但是傳入的引數必須與形參中的型別保持一致,
-
可變個數形參的方法與本類中方法名相同,引數串列不同的方法構成多載,
-
可變個數形參的方法與本類中方法名相同,形參型別也相同的陣列之間不構成多載,
-
可變個數形參在方法的形參中,必須宣告在末尾,
-
因此可變個數形參在方法的形參中,最多只能宣告一個,
public class MethodVarArgsTest {
public static void main(String[] args) {
MethodVarArgsTest test = new MethodVarArgsTest();
test.show(10); // 多載方法1
test.show("hello"); // 多載方法2
test.show("hello","abcdef","12345"); // 可變個數形參方法
test.show(); // 沒有引數也可以呼叫可變形參方法
}
// 多載方法
public void show(int i){
System.out.println("多載方法1");
}
public void show(String s) {
System.out.println("多載方法2");
}
public void show(String ... str) {
System.out.println("可變個數形參方法");
// 使用時,把可變個數形參當作陣列使用
for(int i = 0; i < str.length;i++) {
System.out.println(str[i]); // 當作陣列用
}
}
// 相同型別的陣列會與可變型別方法 不能構成多載,會發生沖突,
/*public void show(String[] strs) {
}*/
// 正確寫法,必須宣告在末尾
public void show(int i, String ... str) {
}
// 錯誤寫法! Vararg parameter must be the last in the list
/*public void show(String ... str, int i) {
}*/
}

方法引數的值傳遞機制
在Java中方法的引數傳遞方式只有一種**值傳遞**,即將實際引數值的副本傳入方法內,而引數本身不受影響,
- 形參是基本資料型別:將實參基本資料型別變數的**
資料值**傳給形參, - 形參是參考資料型別:將實參參考資料型別變數的**
地址值**傳給形參,
練習
練習1
下面代碼的輸出結果是?
class Value {
int i = 15;
}
public class TransferTest3 {
public static void main(String args[]) {
TransferTest3 test = new TransferTest3();
test.first();
}
public void first() {
int i = 5;
Value v = new Value();
v.i = 25;
second(v,i);
System.out.println(v.i); // 20 【傳遞的是地址值】
}
public void second(Value v,int i) {
// v = 25, i = 5
i = 0; // i = 0
v.i = 20; // v = 25
Value val = new Value();
v = val; // v = 15
System.out.println(v.i+" " + i); // 15 0
}
}
練習2
// 下面代碼的輸出結果
public class ArrayPrintTest {
int[] arr = new int[]{1,2,3};
System.out.println(arr); // 地址值
char[] arr1 = new char[]{'a','b','c'};
System.out.println(arr1); // abc
// println(char[]) 的多載方法,會遍歷該char[] 并列印
}
遞回方法
方法遞回(recursion)包含了一種隱式的回圈,它會重復執行某段代碼,但是這種重復執行無須序回圈控制,
遞回一定要向已知方向遞回,否則這種遞回就變成了無窮遞回,類似于死回圈,
/**
* 遞回方法的使用
*/
public class Demo01Recursion {
public static void main(String[] args) {
// 遞回計算1-100所有自然數的和
int n = 100;
int sum = getSum(n);
System.out.println(sum);
// 遞回計算n!
System.out.println(getFact(10));
// 已知有一個數列 f(0) = 1, f(1) = 4, f(n+2) = 2 * f(n+1) + f(n), 求f(10) 的值
// f(n + 2) = 2 * f(n + 1) + f(n);
// f(10) = 2 * f(9) + f(8)
// f(n) = 2 * f(n - 1) + f(n - 2);
System.out.println(f(10));
// 求第n個斐波那契數
System.out.println(Fib(10));
}
// 求和
public static int getSum(int n){
if(n >= 1){
return n + getSum(n-1);
}
return 0;
}
// 求階乘
public static int getFact(int n){
return n == 1? 1 : n * getFact(n-1);
}
// 求f(n)
public static int f(int n){
if(n == 0){
return 1;
} else if(n == 1) {
return 4;
} else {
return 2 * f(n - 1) + f(n - 2);
}
}
// Fibonacci
public static int Fib(int n){
return n <= 2 ? 1 : Fib(n - 1) + Fib(n - 2);
}
}
三大特征之封裝
面向物件三大特征:封裝、繼承、多型,
封裝概述
概述
面向物件編程語言是對客觀世界的模擬,客觀世界里成員變數都是隱藏在物件內部的,外界無法直接操作和修改,
封裝可以被認為是一個保護屏障,防止該類的代碼和資料被其他類隨意訪問,要訪問該類的資料,必須通過指定的方式,適當的封裝可以讓代碼更容易理解與維護,也加強了代碼的安全性,
程式設計追求:高內聚、低耦合,
- 高內聚:類的內部資料操作細節自己完成,不允許外部干涉;
- 低耦合:僅對外暴露少量的方法用于使用,
原則
將屬性隱藏起來,若需要訪問某個屬性,提供公共方法對其訪問,
體現
- 方法就是一種封裝,
- 關鍵字private也是一種封裝,
public class Demo02Method {
public static void main(String[] args) {
int[] arr= {1,2,3,4,5};
int max = getMax(arr);
System.out.println("最大值" + max);
}
public static int getMax(int[] arr){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
max = arr[i] > max ? arr[i] : max;
}
return max;
}
}
// 方法的呼叫者并不關心如何getMax()中的實作細節,它只是呼叫getMax()來完成獲取陣列最大值的功能,
// 將方法封裝起來,就是隱藏細節,對外界不可見,
private關鍵字
private關鍵字用于修飾需要被保護的成員變數,
使用說明
// 創建一個Person 類
public class Person {
String name;
int age;
public void show(){
System.out.println("My name is " + name + ". I'm " + age + " years old");
}
}
// 在main方法中創建一個Person物件
public class Demo03Person {
public static void main(String[] args) {
Person person = new Person();
// 對物件中的成員變數進行賦值
person.name = "Joker";
person.age = -18; // -18 不合理的數值,成員變數無法阻止這個不合法的資料被設定,
person.show();
// private就是用來保護成員變數被賦予這種不合理數值的,
}
}
private關鍵字用來修飾成員變數,被修飾的成員變數,在本類中可以隨意訪問,但是超出本類范圍之外就不能在直接訪問,
// 用private修飾 成員變數 age
public class Person {
String name;
private int age;
// 此時age 不能直接通過 物件名.成員變數名來訪問
public void show(){
System.out.println("My name is " + name + ". I'm " + age + " years old");
}
}

如果想要訪問private修飾的成員變數,就需要使用間接訪問的方法,
間接訪問
間接訪問private修飾的成員變數,就是在本類中定義一對**Getter/Setter方法**,
public class Person {
String name;
private int age;
public void show(){
System.out.println("My name is " + name + ". I'm " + age + " years old");
}
// Setter方法,專門用于設定age的資料
public void setAge(int num){
// 在Setter方法中加入判斷條件,可以有效杜絕成員變數被賦予不合理的值,
if(num <= 150 && num >= 0){
age = num;
} else{
System.out.println("Error,the date of num is corrputed!");
}
}
// Getter方法,專門用獲取age的資料
public int getAge() {
return age;
}
}
public class Demo03Person {
public static void main(String[] args) {
Person person = new Person();
person.name = "Joker";
// person.age = 18; // 此時需要訪問age變數就不能使用直接訪問的方法
person.setAge(18); // 而是使用間接訪問的方法,并將想賦予的值寫在方法呼叫()中
person.show();
int JokerAge = person.getAge(); // 獲取成員變數的值,也應該使用間接訪問方法
System.out.println("Joker's age is " + JokerAge);
}
}

Setter方法
public void setXxx(para) {
// 方法體
}
Setter方法必須有引數,無回傳值;引數型別與要被設定的成員變數保持一致,
命名規則:set + 變數名首字母大寫,
Getter方法
public dataType getXxx() {
// 方法體
}
Getter方法必須有回傳值,無引數,回傳值型別與要設定的成員變數保存一致,
命名規則:get + 變數名首字母大寫,
練習
利用primate關鍵字定義一個學生類
// 利用primate關鍵字定義一個學生類
public class Student {
private String name; // 姓名
private short age;
private boolean male; // true為男,false 為女
public void setName(String str){
name = str;
}
public String getName(){
return name;
}
public void setAge(short num){
age = num;
}
public short getAge() {
return age;
}
public void setMale(boolean b){
male = b;
}
// boolean的Getter方法命名 應該是 isXxxx
public boolean isMale() {
return male;
}
}
注意:
基本資料型別中的boolean值,其Getter方法的命名一定要寫成**isXxxx**
// 使用學生類創建物件
public class Demo04Student {
public static void main(String[] args) {
Student stu = new Student();
stu.setName("張三");
stu.setAge(18);
stu.setMale(true);
System.out.println("姓名:" + stu.getName());
System.out.println("年齡:" + stu.getAge());
String sex = stu.isMale()? "男" : "女";
System.out.println("性別:" + sex);
}
}

this關鍵字
當成員方法中的區域變數,和成員變數重名時,根據"就近原則",優先使用區域變數,
// 定義Person類
public class Person {
String name; // 成員變數
// 成員方法的區域變數名和成員變數名都是name
public void sayHello(String name){ // 區域變數
System.out.println(name + ",您好!我是" + name);
}
}
// 使用Person類創建物件
public class Demo01Person {
public static void main(String[] args) {
Person person = new Person();
person.name = "張三";
person.sayHello("羅翔老師");
}
}
// 結果是成員方法優先使用的是區域變數name

解決方法是使用this關鍵字,
public class Person {
String name; // 姓名
public void sayHello(String name){
System.out.println(name + ",您好!我是" + this.name);
}
}
// this.name 就相當于 person.name

誰呼叫的方法,this就指向誰,
public class Person {
String name; // 姓名
public void sayHello(String name){
System.out.println(name + ",您好!我是" + this.name);
System.out.println(this); // 在成員方法中列印呼叫者的地址,
}
}
public class Demo01Person {
public static void main(String[] args) {
Person person = new Person();
person.name = "張三";
person.sayHello("羅翔老師");
System.out.println(person); // 列印物件名
// 創建不同的物件
System.out.println("========================");
Person person1 = new Person();
person1.name = "李四";
person1.sayHello("羅翔老師");
System.out.println(person1); // 列印物件名
}
}

this 呼叫構造器
- 在類的構造器中,可以顯式的使用
this(形參串列)的方式,呼叫本類中指定的其他構造器, - 構造器中不能通過
this(形參串列)的方式來自己呼叫自己, - 同時構造器之間不可以構成環形呼叫關系,如果一個類中有n個構造器,則最多有
n-1個構造器中可以使用this(形參串列); - 規定:
this(形參串列)必須宣告在當前構造器的首行,也就是構造器內部最多只能宣告一個this(形參串列), - 補充(了解):如果沒有顯式的在構造器中指定呼叫哪一個構造器,那么默認會呼叫super(),用來在子類實體化時先加載父類的結構,
構造器
構造器(constructor)是專門用來創建物件的一種結構,當一個物件被創建時候,構造器用來初始化該物件,給物件的成員變數賦初始值,當我們通過關鍵new來創建物件時,其實就是在呼叫構造器,
tips:無論你與否自定義構造器,所有的類都有構造器,因為Java自動提供了一個空參構造器,一旦自己定義了構造器,Java自動提供的默認無引數構造器就會失效,
構造器的定義格式
修飾符 構造器名(引數型別 引數名稱,...){
// 方法體
}
// 構造器名與所在類名稱完全一樣!
注意事項
- 構造器的名稱必須和所在的類名稱完全一樣,包括大小寫也要一樣,
- 構造器沒有回傳值型別,包括void,
- 構造器不能
return一個具體的回傳值, - 如果沒有自定義構造器,編譯器會自動提供一個無引數構造器,格式如下:
public className() {} // 編譯器默認提供的構造器
- 一旦定義了至少一個構造器,編譯器提供的構造器將失效,
- 構造器可以進行多載,方法名相同,引數串列不同
// 定義一個類,在其中定義構造器
public class Student {
// 成員變數
String name;
int age;
// 構造器可以多載
// 無參構造器
public Student() { // 名字和類名完全一樣
System.out.println("無參構造器執行!");
}
// 全參構造器
public Student(String name, int age) {
System.out.println("全參構造器執行!");
this.name = name;
this.age = age;
}
// Setter/Getter 方法
public void setName(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
}
// 使用類
public class Demo02Student {
public static void main(String[] args) {
// 構造器的呼叫通過new className();
Student stu = new Student(); // 呼叫無參構造器,方法多載
System.out.println("=============================");
Student stu1 = new Student("張三",18); // 呼叫有參構造器,并進行初始化,方法多載
System.out.println("姓名:" + stu1.getName() + " 年齡:" + stu1.age);
System.out.println("=============================");
// Setter方法用來對成員變數重新賦值
stu1.setName("法外狂徒");
stu1.setAge(19);
System.out.println("姓名:" + stu1.getName() + " 年齡:" + stu1.age);
}
}

標準代碼——JavaBean
一個標準的類同時需要擁有下面四個組成部分:
- 所有的成員變數都要使用**
private**關鍵字修飾, - 為每一個成員撰寫一對**
Getter/Setter**方法, - 撰寫一個無引數的構造器,
- 撰寫一個全引數的構造器
這樣一個標準的類也被稱為 Java Bean
public class ClassName{
//成員變數
//構造器
//無參構造器【必須】
//有參構造器【建議】
//成員方法
//getXxx()
//setXxx()
}
舉例
// 定義一個標準的學生類
public class Student {
// 成員變數
private String name; // 姓名
private int age; // 年齡
// 自動生成的無參構造器
public Student() {
}
// 自動生成的全參構造器
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 自動生成的Getter / Setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//使用類
public class Demo01Student {
public static void main(String[] args){
Student stu1 = new Student(); // 呼叫無參構造器
stu1.setName("張三"); // 使用Setter方法賦值
stu1.setAge(18);
// 使用Getter方法獲取值
System.out.println("姓名:" + stu1.getName() + ",年齡:" + stu1.getAge());
System.out.println("====================");
Student stu2 = new Student("李四",19); // 呼叫全參構造器
System.out.println("姓名:" + stu2.getName() + ",年齡:" + stu2.getAge());
System.out.println("====================");
stu1.setName("法外狂徒"); // Setter方法修改值
stu1.setAge(99);
System.out.println("姓名:" + stu1.getName() + ",年齡:" + stu1.getAge());
}
}
static
static主要修飾類的內部結構:屬性、方法、代碼塊、內部類,
被static修飾的內部結構,會隨著類的加載而加載,
修飾屬性
static修飾的屬性,稱作靜態變數,
- 隨著類的加載而加載,
- 在程式運行期間只會被加載一次,
- 屬于類不屬于物件,(權限運行,物件可以呼叫)
- 存在于方法的靜態域中,
使用場景
- 當該屬性可以被多個物件共享時,例如: 國籍、教室等公共的屬性,
- 類中的常量,經常被
static修飾,
static記憶體圖

修飾方法
static修飾的方法,被稱作靜態方法,
- 隨著類的加載而加載,
- 靜態方法中,只能呼叫靜態的方法或屬性,
- 非靜態方法中,既可以呼叫靜態的方法或屬性、也可以呼叫非靜態的方法或屬性,
- 在靜態的方法內,不能使用
this和super關鍵字,
使用場景
- 方法中如果需要操作靜態屬性,同常設定為靜態方法,
- 工具類中的方法,習慣上宣告為
static的,比如:Math、Arrays、Collections
修飾代碼塊
staitc修飾的代碼塊稱為靜態代碼塊,
靜態代碼塊
- 內部可以有輸出陳述句,
- 隨著類的加載而執行,
- 只會在類加載的時候,執行唯一一次,
- 如果一個類中定義了多個靜態代碼塊,則按照宣告的先后順序執行,
- 靜態代碼塊內只能呼叫靜態的屬性,靜態的方法,不能呼叫非靜態的結構,
- 作用:初始化靜態屬性,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/300460.html
標籤:java
