零基础学习java------day7------面向对象
1. 面向對象
1.1 概述
面向過程:c語言
面向對象:java ;python;C++等等
面向對象的概念:
(萬物皆對象)------think in java? ?everything? in an? object
? 把現實中的事務抽象成由一系列屬性和行為組成的結構體(類),每個結構體都有屬于自己的功能,在軟件開發的過程中,通過對不同功能的結構體進行組合,完成整個軟件功能。且結構體可服用
例如;? 若要將現實中的飛機抽象成一個對象
首先你要先定義一個飛機類(看到這個名字就知道是飛機),其次飛機的一些特征如有輪子,有機翼等,這些特征在抽象類中(即類中的代碼中)怎么體現出來呢,這時我們就需要在類中定義一些屬性來表示現實中飛機的這些特性。好了,一個飛機的固有屬性描述完了。但是,其能飛的行為又該怎么來描述呢?這時就需要在類中定義一個‘’飛‘’的方法去表示飛機會飛的行為,飛機的其他行為,如加速減速都需要在類中定義方法去描述。當調用這些方法時,表示的就是飛機對應的行為(如,當調用“飛”方法時,表示的就是飛機飛的行為)。若是不同的飛機類型(如,殲-20,殲-10)該怎么表示呢?這里的話對象就起作用了,這里我們使用airplane1表示飛機殲-20,airplane2表示飛機殲-10,當用airplane1對象調用”飛”方法時,表示的是殲-20飛行的行為,當用airplane2對象調用“飛”方法時,表示的是殲-10飛行的行為。
OO: object-oriented? ? 面向對象
ooa:面向對象的分析
ood:面向對象的設計
oop:面向對象的編程(program)
軟件的生命周期:
需求分析,概要設計,詳細設計,系統開發,系統測試,部署,運行和維護
需求:
存儲全班同學的信息(姓名,性別,分數)
最直觀的想法:利用3個數組去分別存儲姓名,性別,分數,但這樣不便于查找某個學生的性別和分數
所以就需要一種類型能夠將姓名,性別,和分數聚合到一起,那就使用一種自定義的類型-------類
1.2 三大特征
封裝? ? ? ?繼承? ? ? ?多態? ? ? ? (抽象)
1.3 類和對象的關系
類:一種(引用)數據類型,自定義的一種數據類型
對象:具體存在的事物,符合類的定義特征
(1)類的定義:
class 類名{// 屬性,變量// 行為,方法 }類中需要注意的內容:
成員變量,成員方法,靜態變量,靜態方法,局部變量,構造方法
成員變量和靜態變量的區別,一個加static一個不加 如static String name
成員方法和靜態方法的區別:一個有static一個沒有,靜態方法是通過類名調用,而成員方法是通過對象調用
局部變量:定義在方法或者是方法的參數列表上的變量
?
(2) 如何創建對象:
類名? 對象名 = new 類名()
(3) 給對象賦值
對象名.屬性 = 要賦的值
案例
創建一個Teacher 類,包含屬性: 姓名,性別,年齡; 定義一個講課的行為,和自我介紹的方法(用于打印所有的屬性值),創建三個老師對象創建到數組中
創建教師類
// 成員變量---屬性String name;char gender;int age;double salary;
// 成員方法:無static修飾的方法public void teaching() {System.out.println("上課");}public void chuiNiu() {System.out.println("吹牛");}public void show() {System.out.println("我的姓名是" + name + ",性別是" + gender + ",今年" + age);} }
測試類
public class TeacherDemo1 {public static void main(String[] args) {// 創建對象Teacher t1 = new Teacher();t1.name = "老王";t1.gender = '男'; t1.age = 25;t1.salary = 4000;t1.teaching();t1.chuiNiu();t1.show();Teacher t2 = new Teacher();t1.name = "小紅";t1.gender = '女'; //false表示女性t1.age = 28;t1.salary = 5000;t1.teaching();t1.chuiNiu();t1.show();}?
1.4 內存分析
棧(stack):方法的執行,局部變量的存放,其沒有初始值(有指向存放初始值地方(堆)的地址)
?堆:new出來的事物,有初始值,基本數據類型初始值就是默認值,引用數據類型初始值為null? ??
方法區:
class區:所有字節碼文件(.calss),類加載的時候會把相關字節碼文件加載到class區中,同時把用static修飾的事物存入到靜態區
static區:用static修飾的東西
案例(注釋中為運行結果)
public class TeacherDemo {public static void main(String[] args) {Teacher t = new Teacher(); // 上面中的teacher類System.out.println(t); // com._51doit.javase.day7.Teacher@2ff4acd0(此叫全類名:包名+類名)System.out.println(t.name); // nullSystem.out.println(t.age); // 0System.out.println(t.salary); //0.0 } }運行的結果可通過內存分析來理解,如下
大致流程(這里自己也疑惑,就把視頻中老師講的話記錄下來了,感覺老師沒把這塊講清楚,等以后看jvm原理再來修改):
? ? ?程序最開始不是從main方法開始執行,執行main方法前會有個加載的過程,得把類先加載到內存中才能執行。先執行main方法,而main方法的所在的類為TeacherDemo1,所以TeacherDemo1就得編譯成.class文件。然后TeacherDemo1在編譯的過程中發現用到了Teacher類,而要使用這個類,也得進行編譯,并加載到內存當中,否則要用的話就找不到相應的類。其加載至class區域,即變成TeacherDemo1.class? 和Teacher.class。緊接著會加載這兩個字節碼文件,加載的時候若發現有用static修飾的變量和方法就要將其放到static區域,如TeacherDemo1中的靜態方法main就被存放到方法區中的static區,并給其一個地址假設為0x001(若是成員方法就存放在class區,本例中Teacher類中的成員變量都放到了class區)
?????? 當jvm執行時,其就會去找main方法(jvm只認識main方法),通過地址值找到static區域的main方法,然后就會去棧內存執行這個main方法。
首先Teacher t為局部變量,所以就被存儲到棧的main方法中,而new Teacher()被存放到堆中,同時在堆中開辟了一個內存空間,用來存放從class區獲取到的事務(此處時name,gender,age,salary)。由于放到堆里的事務都是有初始值的,所以就要進行賦值(按規則賦值,如int類型賦值0等),此時會賦予這個空間一個地址號,main方法中也會有此地址號(本例為7852e922),前者就可以通過地址號找到后者。Main方法執行完后就從棧中彈出去,因此棧中就無指向堆中的指針,堆中的new Teacher()就通過垃圾回收機制(GC)被回收掉。而方法區一般時jvm停掉后也沒有了,只不過其存放的時間相比堆中會長點(方法存儲區為內存永久帶,不容易被回收)
?
假如在TeacherDemo類中再加入以下代碼,運行的結果會是怎么樣
?
t.name = "張三";t.age = 13;Teacher t1 = new Teacher();t1.name = "李四";t = t1;System.out.println(t.name); // 李四System.out.println(t1.name); // 李四t.age = 80;System.out.println(t1.age); // 80分析如下圖
?
1.5? 成員變量和局部變量的區別
成員變量:定義在類中方法外的變量,沒有static修飾;
局部變量:定義在方法中或者是方法的參數列表上的變量
區別:
(1)在類中的位置不同
成員變量:方法外,類內
局部變量:方法內或者方法的參數列表中
(2)在內存中的位置不同
成員變量:堆內存
局部變量:棧內存
(3)生命周期不同
成員變量:隨著對象的存在而存在,隨著對象的消失而消失
局部變量:隨著方法的調用而存在,隨著方法的調用完畢而消失
(4)初始化值不同
成員變量:有默認的初始值
局部變量:沒有默認的初始化值,必須先定義,賦值,才能使用
?
1.6 匿名對象
匿名對象就是沒有名字的對象,是對象的一種簡化表現形式
匿名對象的兩種使用情況:
(1)對象的調用方法僅僅一次的時候
(2)作為實際參數傳遞
package com._51doit.javase.day7;public class NoNameObjectDemo {public static void main(String[] args) {Teacher t = new Teacher();// 調用屬性時,一般會用命名后的對象.屬性 System.out.println(t.name);System.out.println(t.age);// 下面就是匿名對象,其無名字,結果等價于上面代碼// 注意:下面兩行代碼相當于在堆中開辟了兩個空間// 匿名對象一般不用在調用屬性,因為屬性沒有賦值,調用的也是默認值,沒什么意義,所以匿名對象一般用在調用方法System.out.println(new Teacher().name);System.out.println(new Teacher().age); } }為什么說對象的調用方法僅僅一次?
原因:若調用多次(如下),會創建多個對象,堆中就要開辟多個空間,但若不使用匿名對象,同樣調用多次,只在堆中開辟一個空間,所以使用匿名對象這種情況會浪費空間
new Teacher().show() new Teacher().show() t.show() t.show()匿名對象作為實際參數傳遞
首先在
NoNameObjectDemo類中創建一個test方法,如下:// 注意此處test方法要接受的參數類型為Teacher類型的參數 public static void test(Teacher t) {t.show();}
在main()方法中調用test()方法,代碼如下
test(t);test(new Teacher());// 此即為匿名對象作為參數傳遞
?
1.7 給類重命名的方法
第一種方式,在類文件上右鍵-->refactor-->rename
第二種方式,直接在雷傷改名(代碼中),改完之后將光標放在類明上,根據自動提示,選擇第一個
?
1.8? 形參和實參
形參:定義方法時,方法參數列表上的變量實參:調用方法時,傳進去的具體值
注意:(1)基本數據類型作為參數,形參的改變不影響實參的值,如案例1
(2)引用數據類型作為參數時,形參的改變,影響實參的值(String和包裝類除外),如案例2
包裝類有8種(圖中右邊)
?
package com._51doit.javase.day7;public class ParamDemo {public static void main(String[] args) {sum(12,14); // 12,14為實參 }public static void sum(int a,int b) { // int a和b為形參System.out.println(a+b);} }案例1
下面代碼打印的a值為什么?
package com._51doit.javase.day7;public class ParamDemo {public static void main(String[] args) {int a = 10;change(a);System.out.println(a);}public static void change(int a) {a = 100;} }運行結果: a=10
解釋:
首先執行main()方法(方法的執行時在棧中),所以在棧中就存有一個main方法(入棧),main()方法中有一個局部變量a,并將a存放到main方法中,緊接著是change()方法的執行,所以又會有一個change()方法入棧
change()方法執行完后就出棧,此處給change方法傳了參數a=10,然后方法里面將a改成了100,但是修改后的a值并沒有返回給main方法,所以a打印的值還是為10
?
?案例2
下面代碼打印的值為什么?
?
package com._51doit.javase.day7;public class ParamDemo {public static void main(String[] args) {int[] arr = new int[]{10,20};此處換成新建一個對象并傳遞給相應方法時也是一樣的效果change(arr);System.out.println(arr[0]);System.out.println(arr[1]);}public static void change(int[] arr) {arr[0] = 100;arr[1] = 200; } }運行結果為:100,200
?
?1.9 封裝
?(1)封裝的概述:
指隱藏對象的屬性和實現細節,僅對外提供公共訪問方式。
(2)優點
隱藏實現細節;提高代碼的復用性;提高安全性
(3)封裝原則:
將不需要對外提供的內容都隱藏起來
把屬性隱藏,提供公共方法對其訪問
?實現封裝的步驟
?成員變量私有化:用private修飾成員變量
權限修飾符:
public:修飾類,方法,變量;可在本項目中訪問,跨包需要導包
(default):修飾類,方法,變量,什么都不加,只能在本包中使用
private:修飾方法,變量;被private修飾的方法和變量只能在本類中訪問
提供get和set
get方法:獲取屬性值
public 返回屬性的類型 getXxx(){return 屬性}
set方法:修改屬性值
public void setXxxx(屬性類型? 用來接收屬性值的參數){屬性變量名=用來接收屬性值的參數}
注意點
? ? ? ? ? (1)get方法中需要有返回值,所以public后需接返回屬性的類型,但set方法不需要返回值,所以直接void就行(見案例3)
? ?(2)this關鍵字:
用來區分同名的成員變量和局部變量,this指代成員變量,this看做是一個本類的對象,this所在的方法正在被哪個對象調用,this就指代哪個對象
?
public void setName(String name){// 此處不加this的話就不能區分哪個是參數列表中的name哪個是成員變量namethis.name = name // 若去掉this就會報錯 }具體見案例2
? ? ? ? ? ? ? ? ? ? ? ? ? ??
案例1
創建一個BeautifulGirl類,其包含屬性name,weight,legLenth,并創建一個BeautifulGirlDemo類,在此類中對BeautifulGirl中的屬性進行賦值
package com._51doit.javase.day7.fz;public class BeautifulGirl {String name;double weight;double legLenth; }創建一個BeautifulGirlDemo類
package com._51doit.javase.day7.fz;public class BeautifulGirlDemo {public static void main(String[] args) {BeautifulGirl b1 = new BeautifulGirl();b1.name = "小紅";b1.legLenth = 150;b1.weight = 80;System.out.println(b1.weight);System.out.println(b1.legLenth);} }這種形式可以實現給類或者對象的屬性賦值,但是不安全,使用者(此處是BeautifulGirl)可以隨便修改類或者對象中的屬性,很不安全,為了解決這個問題就出現了封裝,如下
?
防止類中的屬性被隨意訪問和修改,就要將變量私有化(加權限),代碼如下
package com._51doit.javase.day7.fz;public class BeautifulGirl {private String name;private double weight;private double legLenth; }改完之后,eclipse上就會顯示這幾個變量都未被使用,如下圖
?
?同時BeautifulGirlDemo類中的代碼也出現了問題(The field BeautifulGirl.legLenth is not visible),如下
?
說明加上private的修飾后,BeautifulGirlDemo類就無法查看并修改BeautifulGirl類中的屬性(變量)了,但有些時候又要給特定事務提供獲取或修改該私有屬性的方法,這個時候就用到了get方法和set方法,如下
?
?案例2? 使用封裝的特性去實現案例1(這里為例方便,就只寫出了一個name屬性)
創建BeautifulGirl類
package com._51doit.javase.day7.fz;public class BeautifulGirl {// 定義的私有屬性private String name;
// 定義返回name屬性的get方法public String getName() {return name;}
// 定義修改name屬性的set方法public void setName(String name) {this.name = name;} }
創建BeautifulGirlDemo類
package com._51doit.javase.day7.fz;public class BeautifulGirlDemo {public static void main(String[] args) {BeautifulGirl b1 = new BeautifulGirl();b1.setName("小紅");System.out.println(b1.getName());} } // 運行的結果為小紅,說明設置姓名以及訪問這個姓名的屬性成功為什么說這種設置,訪問類或對象屬性的方法更安全呢?因為這里的設置或訪問屬性都是通過調用方法的形式進行的,這種情況下可以在方法中設置前提條件(案例3是在setName和getName方法中加前提條件),設置這個私有屬性誰可以訪問,誰可以修改等
?
練習
?使用封裝的特性創建一個Dog類,類中包括的屬性分別為為name,furColor, gender, age, type,此外要提供get和set方法。在DogTest類中創建2個對象,使用set方法賦值,使用get方法獲取值
?創建Dog類
package com._51doit.javase.day7.fz;public class Dog {private String name;private String furColor;private char gender;private int age;private String type;// name屬性的設置和查看public String getName() {return name;}public void setName(String name) {this.name = name;}// furColor屬性的設置和查看public String getFurColor() {return furColor;}public void setFurColor(String furColor) {this.furColor = furColor;}// gender屬性的設置和查看public char getGender() {return gender;}public void setGender(char gender) {this.gender = gender;}// age屬性的設置和查看public int getAge() {return age;}public void setAge(int age) {this.age = age;}// type屬性的設置和查看public String getType() {return type;}public void setType(String type) {this.type = type;} }創建DogTest類
package com._51doit.javase.day7.fz;public class DogTest {public static void main(String[] args) {Dog d1 = new Dog(); // 創建第一個對象d1d1.setName("旺財");d1.setFurColor("黑色");d1.setGender('公');d1.setAge(3);d1.setType("土狗");Dog d2 = new Dog(); // 創建第二個對象d2d2.setName("富貴");d2.setFurColor("黃色");d2.setGender('母');d2.setAge(2);d2.setType("中華田園犬");System.out.println(d1.getName()+","+d1.getFurColor()+","+d1.getGender()+","+d1.getAge()+","+d1.getType()); // 將屬性獲取并打印出來System.out.println(d2.getName()+","+d2.getFurColor()+","+d2.getGender()+","+d2.getAge()+","+d2.getType());} }?
1.10? 構造方法
構造方法,也叫構造器(constructor),是類中比較特殊的一種方法
(1)格式
修飾符? 類名(參數列表){方法體;}
注意事項:
1. 方法和類名相同
2. 沒有返回值,連void都沒有
3. 構造方法是可以重載的
(2)構造方法何時被調用?
使用new 關鍵字創建對象的時候,就是在調用構造方法
如果要調用其他的構造方法,只需要在new后面的括號中,傳入相應的參數即可
注意:如果我們不在類中創建構造方法,那么系統會為我們自動生成無參數的構造方法,但若我們在類中寫了構造方法,那么系統則不再為我們生成
?
案例1? 上面dog類的練習中,利用構造方法給變量賦值(傳參)
直接在Dog類中添加一下代碼,如下
1 public class Dog { 2 public Dog() {}; 3 public Dog(String name,int age,String furColor,String type,char gender) { 4 this.name = name; 5 this.furColor = furColor; 6 this.gender = gender; 7 this.age = age; 8 this.type = type; 9 }; 10 //下面的代碼同上訴Dog類這時就不需要set來給變量賦值,直接在新創建的對象中傳實參就行,如下
Dog d3 = new Dog("小強",12,"哈士奇","紫色",'母'); System.out.println(d3.getName()+","+d3.getFurColor()+","+d3.getGender()+","+d3.getAge()+","+d3.getType());由低2和第3行的代碼可知,構造方法是重載的,新建的對象會根據參數類型找相應的構造方法
注意:若將第二行代碼去掉,則原先創建的無參數的對象就找不到對應的構造方法就會報錯(自己創建了構造方法,就不會自動生成默認的無參數的構造方法了)
?
1.11 六大組件
成員變量
靜態變量
局部變量
成員方法
靜態方法
構造方法
?
1.12 給對象賦值的方式(前面內容也涉及,這里總結在一起)
第一種
對象名.屬性名= 要賦的值
Teacher t = new Teacher(); t.name = “zhang san”;第二種
使用set 方法:
t.setName(“李四”);第三種
使用構造方法
Teacher t = new Teacher(“趙柳”,19); class Teacher{public Teacher(String name,int age){this.name = name;this.age = age;} }?
1.13 作業
1.?定義一個類Demo,其中定義一個求兩個數據和的方法,定義一個測試類Test,進行測試。
?
public class AddDemo {double a;double b;public AddDemo(double a, double b) {this.a = a;this.b = b;}public double getSum() {return a+b;} }測試類
import java.util.Scanner;public class AddDemoTest {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("請輸入第一個數");double a = sc.nextDouble();System.out.println("請輸入第一個數");double b = sc.nextDouble();AddDemo ad1 = new AddDemo(a, b);System.out.println("兩數的和為:" + ad1.getSum());} }隨意輸入兩個數,即可得到加和的值
2?定義一個長方形類,定義求周長和面積的方法,然后定義一個測試了Test2,進行測試。
public class Circle {private double r;private double pi;// r的獲取和設置public double getR() {return r;}public void setR(double r) {this.r = r;}// pi的獲取和設置public double getPi() {return pi;}public void setPi(double pi) {this.pi = pi;}// 求圓面積public double cirArea() {return pi*r*r;}// 求圓的周長public double cirGirth() {return 2*pi*r;} }測試類
import java.util.Scanner;public class CircleTest {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("請輸入r的值");double r = sc.nextDouble();System.out.println("請輸入pi的值");double pi = sc.nextDouble();Circle c1 = new Circle();c1.setR(r) ;c1.setPi(pi);System.out.println("圓的面積為:"+ c1.cirArea());System.out.println("圓的周長為:"+ c1.cirGirth());} }3.?定義一個員工類,自己分析出幾個成員,然后給出成員變量,構造方法,getXxx()/setXxx()方法,以及一個顯示所有成員信息的方法。并測試。
4.?定義一個類MyMath,提供基本的加減乘除(add,sub,mul,div)功能,然后進行測試。
?
轉載于:https://www.cnblogs.com/jj1106/p/11314291.html
總結
以上是生活随笔為你收集整理的零基础学习java------day7------面向对象的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CSS 使网页变灰(文字加动画)
- 下一篇: step4 . day5 进程与进程的创