Java學習的第五天
1.關鍵字this的使用:this表示每個執行個體對象指向自己的引用,可以出現在執行個體化方法和構造方法中,不能出現在由static修飾的類方法中
-
在執行個體方法和構造方法中使用this
this可以出現在類的構造方法和非static修飾的成員方法(也就是執行個體方法)中,this代表執行個體對象自身,可以通過this來通路執行個體對象的成員變量或者調用成員方法。了解不了,不慌,看代碼:
public class TestThis {
public String catColor;
public int catHeight;
//一個方法表示哭
public void cry(){
System.out.println("我是一個"+this.catColor+"貓,我正在哭,你聽,喵喵喵");
}
//一個方法表示長大了
public void grow(){
this.catHeight++;
System.out.println("調用這個方法,我就會長高,而且我的升高是"+this.catHeight+"cm");
}
//但是構造方法不能省略public
//第一個構造方法
public TestThis(String color){
this.catColor=color;
this.cry();
}
//第二個構造方法
public TestThis(String color,int height){
this(color);
this.catHeight=height;
}
public static void main(String[] args) {
TestThis cat=new TestThis("黃",12);//此時會調用構造函數,也就是說,這裡必須由參數,因為沒有聲明無參構造函數
cat.grow();
cat.grow();
}
}
結果為:
我是一個黃貓,我正在哭,你聽,喵喵喵
調用這個方法,我就會長高,而且我的升高是13cm
調用這個方法,我就會長高,而且我的升高是14cm
分析以下代碼:這裡this有幾個點:1.當new一個對象時,會進行執行個體化,傳入的是兩個參數,一個是顔色,一個是身高。那麼意味着會通過參數類型進入第二個構造方法。這個時候,就需要知道this調用方法:類中的方法一共有兩種:普通方法(執行個體方法):this.方法名稱(參數…),構造方法:this(參數…)。是以,"黃"這個字元串就進入了this(color)方法;這裡就是this調用構造方法了,此時,會調用第一個構造方法,輸出語句:我是一個黃貓,我正在哭,你聽,喵喵喵,然後,将傳入的身高值,賦給catHeight。
-
區分成員變量和局部變量
成員變量在整個類中有效,局部變量僅在方法内有效。在方法體中的聲明變量以及方法的傳入參數均稱為局部變量,局部變量隻有在方法體内有效。如果執行個體方法中,或類方法中的局部變量名字和成員變量名字相同,這個成員變量在這個方法内暫時失效。(說個人話,變量名一般不一樣不就解決了麼,隻有面試題會有這些東西)如果确實想引用成員變量,則可以使用this關鍵字。代碼如下:
public class TestThis2 {
int x=188;
int y;
public void f(){
int x=3;
y=x;
System.out.println("此時y的值"+y);
y=this.x;
System.out.println("此時y的值"+y);
}
public static void main(String[] args) {
TestThis2 this2=new TestThis2();
this2.f();
}
}
結果為:
此時y的值3
此時y的值188
分析一下:第一個将x的值賦給y,此時x必然是局部變量,因為優先呀(如果執行個體方法中,或類方法中的局部變量名字和成員變量名字相同,
這個成員變量在這個方法内暫時失效。),第二個x的值賦給y,此時用到了this關鍵詞,那就是引用成員變量,是以就是188
-
傳回執行個體對象本身的引用
this還可以作為類成員方法的return語句參數,用來傳回對象本身的引用。→return this。這個this此時表示的就是對象本身。代碼如下:
public class TestThis3 {
int age;
float height;
public TestThis3(){//這裡是無參的
age=1;
height=10;
}
//下面這個方法沒有使用void是因為有傳回值,同時看到傳回值的類型是TestThis3
//看到這裡不要慌,不需要具體了解TestThis3是什麼類型,當我們new一個對象時,那個對象的類型,就是類
public TestThis3 grow(){
height=height+10;
age++;
return this;
}
public static void main(String[] args) {
TestThis3 this3=new TestThis3();//注意上下文,這裡也無參,其實這裡有些寓意,代表剛剛出生
System.out.println("剛剛出生的this3的升高是"+this3.height+"年齡是"+this3.age);
this3=this3.grow();
System.out.println("剛剛出生的this3的升高是"+this3.height+"年齡是"+this3.age);
}
}
結果為:
剛剛出生的this3的升高是10.0年齡是1
剛剛出生的this3的升高是20.0年齡是2
分析代碼return this;代表着什麼,記住,此時的this代表的是對象本身,因為聲明方法時,就是public TestThis3 grow(),這就意味必須有傳回值,就是TestThis3這個位置,隻要不是void,就得有傳回值,簡單說int型也得有,對象本身就是this3,而且必須傳回構造方法裡面的參數内容的值,有些抽象,多了解。
- 使用this調用類的其他構造方法 this調用方法:類中的方法一共有兩種:普通方法(執行個體方法):this.方法名稱(參數…),構造方法:this(參數…)。看上面代碼就好了
- 類方法中不能使用this:類方法就不需要對象,筆試題會有。
2.面向對象的特性。總共有4個,面試必備
-
第一個特性———封裝:将實體特征的屬性隐藏起來,對象與外界僅通過公共方法進行交流,這樣 可以提高程式的可靠性,安全性,改善程式的可維護性。資料的隐藏與開放對外的接口可以通過通路權限控制符來實作,權限控制符來設定類,成員變量,成員方法等通路權限。Java提供了public,private,protected,預設等4種通路控制符。這個問題說了很多次了,不要煩,我打字更麻煩,看代碼。(這裡會涉及到包,之前我們也講過,會先給大家看截圖)
每一個JavaTest都是一個包,包裡可以有類名相同的存在
第一個是main方法,用來運作類的(注意包名),當然結果也是在這裡輸出
package JavaTest3;//這裡是包
public class Main {
public static void main(String[] args) {
Student daunSang= new Student(19, "山西太原", "段桑", 1716);
Teacher caoCao = new Teacher(35, "四川成都", "曹操", 20201716, "2020001");
caoCao.question(daunSang);
}
}
結果為:
學生的位址:山西太原 學生的年齡:19 學生的名字:段桑
第二個是學生的
package JavaTest3;
public class Student {
public int studentAge;
protected String studentAddr;
String studentName; //預設權限
private int studentAccount;
public Student(int studentAge,String studentAddr,String studentName,int studentAccount){
//這裡說一下,this表示的是對象本身,但是前提是執行個體化以後,注意
//假設Student duanSang=new Student();此時this就相當于duanSang
this.studentAccount=studentAccount;
this.studentAddr=studentAddr;
this.studentAge=studentAge;
this.studentName=studentName;
}
public Student(){
this.studentAge=18;
}
}
第三個是manger的,繼承了學生類,學生類的一個子類
package JavaTest3;
public class Manger extends Student {
//該類繼承了student類,用來測試同一包内子類的權限控制
void getStudentInfo(){
System.out.println("名字是:"+studentName);
System.out.println("年齡是:"+studentAge);
//System.out.println("賬戶是:"+studentAccount);
// 當使用了IDEA編譯工具時,會自動提示,沒有studentAccount,也就是說private修飾的不能被相同包的子類通路
System.out.println("位址是:"+studentAddr);
}
}
第四個是teacher對的
package JavaTest3;
public class Teacher {
public int age;
protected String addr;
String name;
private int account;
String teacherID;
public Teacher(int age,String addr,String name,int account,String teacherID){
this.account=account;
this.addr=addr;
this.age=age;
this.name=name;
this.teacherID=teacherID;
}
public void setInfo(String teacherID){
this.teacherID=teacherID;//當傳入teacherID時,會賦給對象
}
public void question(Student student){
System.out.println("學生的位址:"+student.studentAddr+"\t學生的年齡:"+student.studentAge+"\t學生的名字:"+student.studentName);
//System.out.println("學生的賬戶"+student.studentAccount);studentAccount報紅,意味着通路不到
}
}
分析一下:首先,除了Main類是用來調用main方法的,剩下三個,Manger,Student,Teacher是屬于一個檔案的,其中Manger是Student的子類。Student的屬性 studentAge 、studentAddr 、 studentName均可以被Manger,Teacher通路和使用,而private修飾的studentAccount不能被Manger,Teacher通路和使用。這裡圖檔很重要,注意看,注意看
屬于封裝的---------getInfo與 setInfo
答:出于系統設計的安全性考慮,一般将類的成員屬性定義為private形式保護起來,而将類的成員方法定義為public形式對外公開,這是類封裝特性的一個展現。一般來說,類中應提供相應的get方法(得private成員變量的值)和set方法(修改private成員變量的值),以便其他類的操作該類的private成員變量。代碼如下:
public class StudentInfo {
public String name;
public String studentID;
private String address;
public String phone;
protected String major;
private float GPA;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStudentID() {
return studentID;
}
public void setStudentID(String studentID) {
this.studentID = studentID;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public float getGPA() {
return GPA;
}
public void setGPA(float GPA) {
this.GPA = GPA;
}
//有一個一鍵生成,右擊滑鼠,找到Generate,裡面有getter和setter方法
//同理:構造方法也有
public StudentInfo(String name, String studentID, String address, String phone, String major, float GPA) {
this.name = name;
this.studentID = studentID;
this.address = address;
this.phone = phone;
this.major = major;
this.GPA = GPA;
}
public void getStudentInfo(){
System.out.println("姓名:"+name+"\t學号:"+studentID+"\t住址:"+address+"\t電話:"+phone+"\t專業:"+major+"\t績點:"+GPA);
}
public static void main(String[] args) {
StudentInfo studentInfo1=new StudentInfo("段桑","20201716","山西太原","182xxxx3691","java",3.0f);
studentInfo1.setGPA(3.9f);
studentInfo1.getStudentInfo();
}
}
結果為:
姓名:段桑 學号:20201716 住址:山西太原 電話:182xxxx3691 專業:java 績點:3.9
分析代碼:set和get方法,按照常理來說,就是修改或擷取值
首先在main方法中,new了一個對象,并且,為所有值都附了初始值,此時如果使用get方法,全部都可以獲得,在代碼中使用了setGPA()方法,修改了績點,原來初始值是2.0f,修改完以後變為3.9f。
2.第二個特性———繼承子類繼承父類,父類派生子類,子類還可以在派生子類。(繼承就是叫爸爸,派生就是,他是你兒子)繼承的關鍵字使用是extends→格式:class 子類名 extends 父類名【implements<接口名>】(如果說沒有使用extends關鍵字,也就是說此時程式員沒有去給他繼承一個父類,那麼預設他的父類是Java.lang.object類,object類是所有預定義類的父類(Object類是Java中唯一沒有父類的類),包含了所有Java的公共屬性,常見的有equals(Object obj),hashCode(),toString()等等)
在剛剛的代碼中也寫了繼承的例子,但是這裡再來一個:
第一個main方法:
package JavaTest3;
public class Main2 {
public static void main(String[] args) {
Manager manager=new Manager();
manager.setName("段桑");
manager.setDepartment("技術部");
manager.setSalary(15000);
manager.setSpecial("技術部老大");
manager.setSubsidy(1200);
System.out.println("-----------------------------------員工資訊--------------------------------------");
System.out.println();//換行
System.out.println(manager.toString());
}
}
結果為:
-----------------------------------員工資訊--------------------------------------
Manager{special='技術部老大', subsidy=1200.0, name='段桑', salary=15000.0, department='技術部'}
第二個是Employee類
package JavaTest3;
public class Employee {
protected String name;
protected double salary; //工資
protected String department;//部門
//換記得generate麼,右擊查找
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
//toString()方法是用來列印(輸出)剛剛聲明的内容:name ; salary ; department
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", salary=" + salary +
", department='" + department + '\'' +
'}';
}
}
第三個是:
package JavaTest3;
public class Manager extends Employee{
//聲明時修飾符時private,也就是說這是Manager特有的
private String special;//職位
private double subsidy;//補貼
//老規矩,一鍵生成
public String getSpecial() {
return special;
}
public void setSpecial(String special) {
this.special = special;
}
public double getSubsidy() {
return subsidy;
}
public void setSubsidy(double subsidy) {
this.subsidy = subsidy;
}
//由于繼承,一鍵生成時,就會多了幾個選擇,哈哈哈,IDEA好用
@Override
public String toString() {
return "Manager{" +
"special='" + special + '\'' +
", subsidy=" + subsidy +
", name='" + name + '\'' +
", salary=" + salary +
", department='" + department + '\'' +
'}';
}
}
代碼分析:在上面的代碼中為了實作功能,是以在Employee類中沒有定義private的成員變量,通過封裝那張圖,可以看到,就算是相同包内的子類,也是不能通路父類的private修飾的成員變量。最主要的點在于,main方法中,Manager manager=new Manager();但是,對象manager可以調用Employee類中的方法。
屬于繼承的------super的使用(筆試,面試都會問的)
-
子類在繼承父類時,可能會出現變量隐藏,方法覆寫等現象。**變量隐藏指子類的成員變量與父類成員同名,此時父類的成員變量隐藏。方法覆寫是指子類的方法名與父類的方法名重名,方法的傳回值類型,入口參數的數目,類型,順序都相同,隻是方法實作的功能不同,此時父類的方法被覆寫。**如果子類需要調用或通路父類被隐藏的變量或被覆寫的方法,可以使用super關鍵字實作。(有點類似this在局部變量與成員變量的使用)代碼如下:
關鍵在于第三個:BClass類,請好好看
第一個是main方法
package JavaTest3;
public class Main3 {
public static void main(String[] args) {
AClass aClass=new AClass();
BClass bClass=new BClass();
aClass.p1();
bClass.p1();
}
}
結果為:
這是方法A
a=50
這是方法B
a=10
這是方法A
a=50
super.a=50
第二個是AClass類:
package JavaTest3;
public class AClass {
int a;
float a1;
public AClass(){
a=50;
a1=99.99f;
}
public void p1(){
System.out.println("這是方法A");
System.out.println("a="+a);
}
}
第三個是:BClass類:
package JavaTest3;
public class BClass extends AClass {
int a;//與父類的成員變量名相同,屬于變量隐藏現象
public BClass(){
a=10;
a1=123.4f;
}
//與父類的成員方法相同,屬于方法覆寫現象
public void p1(){
System.out.println("這是方法B");
System.out.println("a="+a);//此處的a是BClass的變量值
super.p1();//通過super關鍵字調用被覆寫的父類成員方法
System.out.println("super.a="+super.a);//通過super關鍵字調用被隐藏的父類成員變量
}
}
-
子類對象的構造:當用子類的構造方法建立一個子類對象時,子類的構造方法總會顯式或隐式的先調用父類的某個構造方法。如果子類的構造方法沒有明顯的指明調用父類的那個構造方法,Java會預設調用父類的無參構造方法;子類也可以根據super顯式的調用父類的指定的構造方法,具體是哪一個構造方法要根據super的參數類型決定。代碼分析:
第一個是main方法:
package JavaTest3;
public class MainSuper {
public static void main(String[] args) {
SuperClassSon superClassSon1=new SuperClassSon();
SuperClassSon superClassSon2=new SuperClassSon(400);
}
}
結果為:
調用父類的有參構造方法SuperClass(300)
調用子類的無參構造方法
調用父類的無參構造方法
調用子類的有參構造方法SuperClassSon(400)
第二個是SuperClass 父類
package JavaTest3;
public class SuperClass {
private int n;
//父類聲明兩個構造函數,一個無參,一個有參
public SuperClass(){
System.out.println("調用父類的無參構造方法");
}
public SuperClass(int n){
System.out.println("調用父類的有參構造方法SuperClass("+n+")");
this.n=n;
}
}
第三個是SuperClassSon 子類
package JavaTest3;
public class SuperClassSon extends SuperClass{
private int n;
//子類的構造方法
public SuperClassSon(){
super(300);//通過super顯式的調用父類特定的構造方法
System.out.println("調用子類的無參構造方法");
}
public SuperClassSon(int n){
super();//可以通過super調用父類的構造方法,其實是預設
System.out.println("調用子類的有參構造方法SuperClassSon("+n+")");
this.n=n;
}
}
代碼分析:當子類建立時,系統會預設自動調用父類的無參構造方法,也就是如果沒有用super去特定的指明(根據super()的參數決定),Java預設調用父類的無參構造方法。例如:main方法中SuperClassSon superClassSon2=new SuperClassSon(400);執行個體化對象,初始化構造方法有參數的,但是,此時的super()中沒有任何參數,也就是說調用父類的無參構造方法,是以這個語句有沒有,都不影響結果,反正Java會預設調用,是要super()不去特定的指明。
-
對象類型轉換:Java中的子類對象可以向上轉換為父類對象,例如:SuperClass superClass=new SuperClassSon();父類的方法,變量,子類可以去使用。
3.第三個特性———多态:同一操作作用于不同類的執行個體,将産生不同的執行結果,即不同類的對象收到相同的消息時,得到不同的結果。
- 多态性包含編譯時的多态性和運作時的多态性兩大類,即多态性也分為靜态多态性和動态多态性。
- 靜态多态性是指定義在一個類或一個函數中的同名函數,根據參數表(類型以及個數)差別語義和執行的功能(說白了,就是重載)。
- 動态多态性是指定義在一個類層次的不同類中的重載函數,他們具有相同的函數原型,需要根據指針指向對的對象所在類來差別語義,他通過動态聯編實作。
-
**Java從多個方面支援動态性,一方面可以通過方法重載實作多态;另一方面也可以通過繼承過程中出現的方法覆寫以及對象類型的轉換(父類引用指向子類)實作。**代碼如下:
第一個main方法:
package JavaTest4;
public class Main {
public static void main(String[] args) {
Lady missGao=new Lady();
missGao.pet=new Dog();
missGao.petEnjoy();
Lady missDuan=new Lady();
missDuan.pet=new Bird();
missDuan.petEnjoy();
}
}
結果為:
旺旺旺旺........
喳喳喳喳........
第二個為Pet 類:
package JavaTest4;
public class Pet {
int name;
void enjoy(){
System.out.println("寵物高興");
}
}
第三個為Lady 類:
package JavaTest4;
public class Lady {
Pet pet;
void petEnjoy(){
pet.enjoy();
}
}
第四個為Dog ,Bird 子類:
package JavaTest4;
public class Dog extends Pet{
void enjoy(){
System.out.println("旺旺旺旺........");
}
}
package JavaTest4;
public class Bird extends Pet {
void enjoy(){
System.out.println("喳喳喳喳........");
}
}
代碼分析:Lady類的成員變量pet是父類對象。missDuan.pet父類引用指向了子類對象(一個鳥的執行個體對象),missGao.pet父類引用也同樣指向了子類對象(一個狗的執行個體對象)。此時父類引用指向子類對象,Java隻能根據父類引用的具體指向。選擇不同類的方法,實作了用相同的接口完成不同的功能。在pet的子類中,和父類有一樣的方法,此時進行了重寫,覆寫掉原來的語句,實作了多态
4.第四個特性———抽象