一、面向?qū)ο蟮某醪秸J(rèn)知
1.1 什么是面向?qū)ο?/h4>
Java是一門純面向?qū)ο蟮恼Z言(Object Oriented Program,簡(jiǎn)稱OOP),在面向?qū)ο蟮氖澜缋铮磺薪詾閷?duì)象。面向?qū)ο笫墙鉀Q問題的一種思想,主要依靠對(duì)象之間的交互完成一件事情
1.2 面向?qū)ο笈c面向過程
注意:面向過程和面相對(duì)象并不是一門語言,而是解決問題的方法,沒有那個(gè)好壞之分,都有其專門的應(yīng)用場(chǎng)景
(1)面向過程:類似于傳統(tǒng)把大象放進(jìn)冰箱的過程,打開冰箱->把大象塞進(jìn)去->把冰箱關(guān)上
這種方式注重的是把大象放進(jìn)冰箱的過程,少一個(gè)環(huán)節(jié)都不行。如果要把其他東西放進(jìn)冰箱又是另一種方式。
按照該種方式來寫代碼,將來擴(kuò)展或者維護(hù)起來會(huì)比較麻煩
(2)面向?qū)ο螅?/p>
總共有四個(gè)對(duì)象:人、衣服、洗衣粉、洗衣機(jī)
整個(gè)洗衣服的過程:將衣服放進(jìn)洗衣機(jī)、倒入洗衣粉,啟動(dòng)洗衣機(jī),洗衣機(jī)就會(huì)完成洗衣過程并且甩干
整個(gè)過程主要是:人、衣服、洗衣粉、洗衣機(jī)四個(gè)對(duì)象之間交互完成的,人不需要關(guān)新洗衣機(jī)具體是如何洗衣服的,是如何甩干的
以面向?qū)ο蠓绞絹磉M(jìn)行處理,就不關(guān)注洗衣服的過程,具體洗衣機(jī)是怎么來洗衣服,如何來甩干的,用戶不用去關(guān)心,只需要將衣服放進(jìn)洗衣機(jī),倒入洗衣粉,啟動(dòng)開關(guān)即可,通過對(duì)象之間的交互來完成的
二、類定義和使用
2.1 簡(jiǎn)單認(rèn)識(shí)類
類是用來對(duì)一個(gè)實(shí)體(對(duì)象)來進(jìn)行描述的,主要描述該實(shí)體(對(duì)象)具有哪些屬性(外觀尺寸等),哪些功能(用來干啥),描述完成后計(jì)算機(jī)就可以識(shí)別了(類似C語言中的結(jié)構(gòu)體)
比如:洗衣機(jī),它是一個(gè)品牌,在Java中可以將其看成是一個(gè)類別。
屬性:產(chǎn)品品牌,型號(hào),產(chǎn)品重量,外觀尺寸,顏色...
功能:洗衣,烘干、定時(shí)....
2.2 類的定義格式
在java中定義類時(shí)需要用到class關(guān)鍵字
//創(chuàng)建類
class ClassName {
field; //字段(也叫屬性或者成員變量)
method; //行為(也叫成員方法)
}
class為定義類的關(guān)鍵字,ClassName為類的名字,{ }中為類的主體
類包括兩部分:
(1)成員變量(字段\屬性):用來描述類的 (這些成員變量定義在方法外部,類的內(nèi)部)
(2)成員方法(行為):說明類具有哪些功能
class WashMachine { //此時(shí)的WashMachine就是自定義的類型
//成員變量(字段\屬性)
public String brand;
public String type;
public double weight;
public double length;
public double width;
public double height;
public String color;
//成員方法(行為)
public void washClothes() {
System.out.println("洗衣服功能");
}
public void dryClothes() {
System.out.println("脫水功能");
}
public void setTime() {
System.out.println("定時(shí)功能");
}
}
采用Java語言將洗衣機(jī)類在計(jì)算機(jī)中定義完成,經(jīng)過javac編譯之后形成.class文件,在JVM的基礎(chǔ)上計(jì)算機(jī)就可以識(shí)別了
注意事項(xiàng):
(1)類名采用大駝峰定義
(2)成員前統(tǒng)一寫public,后面會(huì)解釋
(3)成員方法不帶static關(guān)鍵字,后面會(huì)解釋
(4)一般一個(gè)文件當(dāng)中只定義一個(gè)類(一個(gè)文件可以有多個(gè)類,但是最多只能有一個(gè)被public修飾的類,且這個(gè)被修飾的類的名稱必須和Java文件名一致)
(5)main方法所在的類一般要使用public修飾(Eclipse默認(rèn)會(huì)在public修飾的類中找main方法)
(6)不要輕易去修改public修飾的類的名稱,如果要修改,通過開發(fā)工具修改
(在idea中右擊創(chuàng)建的文件->refactor->rename )
如果一個(gè)文件有多個(gè)類,則只會(huì)改文件名,不會(huì)改變類名
三、類的實(shí)例化
定義了一個(gè)類 == 在計(jì)算機(jī)中定義了一種新的類型(與int,double類似)
類的實(shí)例化 == 用自定義的類型創(chuàng)建變量(對(duì)象)(占用實(shí)際的物理空間存儲(chǔ)類成員變量)
比如上面的WashMachine類,有了自定義類型之后,就可以用這些類來定義實(shí)例(對(duì)象)
在java中采用new關(guān)鍵字,配合類名來實(shí)例化對(duì)象
創(chuàng)建一個(gè)狗類:
class PetDog {
//狗的屬性
public String name;
public String color;
//狗的行為
public void barks() {
System.out.println(name+"汪汪汪~~~");
}
public void wag() {
System.out.println(name+"搖尾巴~~~");
}
}
類的實(shí)例化:
public class demo {
public static void main(String[] args) {
//第一只狗:旺財(cái)-黑色
PetDog dog1 = new PetDog();
dog1.name = "旺財(cái)";
dog1.color = "黑色";
dog1.barks();
dog1.wag();
//第二只狗:阿黃-棕色
PetDog dog2 = new PetDog();
dog2.name = "阿黃";
dog2.color = "棕色";
dog2.barks();
dog2.wag();
}
}
內(nèi)存中的形式:?
?
? ? ? ? ? ? ? ? 虛擬機(jī)棧? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 堆
運(yùn)行結(jié)果:
注意事項(xiàng):?
(1)new關(guān)鍵字用來創(chuàng)建一個(gè)對(duì)象實(shí)例(只要new就會(huì)產(chǎn)生新的對(duì)象,只要是新的對(duì)象就是有新的內(nèi)存)
(2)使用 .? ?? 來訪問對(duì)象中的屬性和方法
(3) 同一個(gè)類可以創(chuàng)建多個(gè)對(duì)象實(shí)例
四、this引用
4.1? 為什么要有this引用
class Date {
public int year;
public int month;
public int day;
public void setDay(int y,int m,int d) {
year = y;
month = m;
day = d;
}
public void printDate() {
System.out.println(year+"/"+month+"/"+day);
}
}
public static void main(String[] args) {
//創(chuàng)建一個(gè)日期類型的對(duì)象d1
Date d1 = new Date();
//對(duì)d1的日期設(shè)置
d1.setDay(2022,9,15);
//打印日期
d1.printDate();
}
以上代碼定義了一個(gè)日期類,然后main方法中創(chuàng)建了一個(gè)對(duì)象,并通過Date類中的成員方法對(duì)對(duì)象進(jìn)行設(shè)置和打印,代碼整體邏輯非常簡(jiǎn)單,沒有任何問題
但是思考一定還是有問題存在:
如果形參名不小心與成員變量名相同:那函數(shù)體中到底是誰給誰賦值?成員變量給成員變量?參數(shù)給參數(shù)?參數(shù)給成員變量?成員變量參數(shù)?估計(jì)自己都搞不清楚了(這是由于局部變量?jī)?yōu)先,就與方法外部的year,month,day無關(guān)了)
public void setDay(int year,int month,int day) {
year = year;
month = month;
day = day;
}
4.2 什么是this引用
this引用指向當(dāng)前對(duì)象(誰調(diào)用了當(dāng)前方法誰就是this),在成員方法中所有成員變量的操作,都是通過該引用去訪問。
public void setDay(int year,int month,int day) {
this.year = year;
this.month = month;
this.day = day;
}
4.3 this引用的特性
(1)this的類型:對(duì)應(yīng)類類型引用,即哪個(gè)對(duì)象調(diào)用就是哪個(gè)對(duì)象的引用類型(類類型都是引用類型)
(2)this只能在"成員方法"中使用
(3)? ?在"成員方法"中,this只能引用當(dāng)前對(duì)象,不能再引用其他對(duì)象
(4)this是“成員方法”第一個(gè)隱藏的參數(shù),編譯器會(huì)自動(dòng)傳遞,在成員方法執(zhí)行時(shí),編譯器會(huì)負(fù)責(zé)將調(diào)用成員方法對(duì)象的引用傳遞給該成員方法,this負(fù)責(zé)來接收
編譯器編譯會(huì)把this參數(shù)還原:
class Date {
public int year;
public int month;
public int day;
public void setDay(Date this,int year,int month,int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void printDate(Date this) {
System.out.println(this.year+"/"+this.month+"/"+this.day);//這里建議自己加this
}
}
this的三種使用方式:
<1>this.成員變量? ? -> 訪問成員變量
<2>this.func( )? ? ?_>? 訪問當(dāng)前的成員方法?
<3>this()調(diào)用當(dāng)于類的構(gòu)造方法
在這里有幾個(gè)問題:大家一起思考一下:
(1)引用可以指向引用嗎?
答:不對(duì),引用只能指向?qū)ο?/span>
Dog dog1 = new Dog();
Dog dog2 = dog1;
dog2這個(gè)引用并不是指向了dog1這個(gè)引用,而是指向了dog1這個(gè)引用指向的對(duì)象
(2) 一個(gè)引用可以同時(shí)指向多個(gè)對(duì)象嗎?
答:不可以,一個(gè)引用只能指向一個(gè)對(duì)象
Dog dog1 = new Dog();
dog1 = new Dog();
dog1 = new Dog();
dog1 = new Dog();
最終dog這個(gè)引用只能有一個(gè)對(duì)象的地址
(3)Dog dog2? = null代表dog2這個(gè)引用指向一個(gè)null對(duì)象?
答:不正確,dog2這個(gè)引用不指向任何對(duì)象
交換兩個(gè)數(shù)的值:
我們知道Java中是不能直接交換兩個(gè)數(shù)的值(基本類型傳遞進(jìn)行的就是值傳遞,基本類型的變量是在虛擬機(jī)棧上的,無法將地址或者引用傳遞,swap交換的是swap中的形參a和b,并不會(huì)影響到實(shí)參a和b)??
class MyValue {
public int val;
public MyValue(){
}
}
public class code {
//交換兩個(gè)類中數(shù)的方法
public static void swap(MyValue val1,MyValue val2) {
int tmp = val1.val;
val1.val = val2.val;
val2.val = tmp;
}
public static void main(String[] args) {
//創(chuàng)建myValue1
MyValue myValue1 = new MyValue();
myValue1.val = 10;
//創(chuàng)建myValue2
MyValue myValue2 = new MyValue();
myValue2.val = 20;
System.out.println("交換前:"+myValue1.val);
System.out.println("交換前:"+myValue2.val);
swap(myValue1,myValue2);
System.out.println("交換后:"+myValue1.val);
System.out.println("交換后:"+myValue2.val);
}
}
運(yùn)行結(jié)果:?
?
結(jié)果分析:
創(chuàng)建好va1和val2變量后:
?
然后swap創(chuàng)建tmp交換引用?
tmp拿到val1的引用(地址),val1的引用等于val2的引用,val2的引用等于tmp的引用
然后跳出swap方法,val1和val2就沒了,但是引用還在,并且兩個(gè)引用的值進(jìn)行了交換,所以最終交換成功
五、對(duì)象的構(gòu)造及初始化
5.1 如何初始化對(duì)象
在Java方法內(nèi)部定義一個(gè)局部變量時(shí),必須要初始化,否則會(huì)編譯失敗
public static void main(String[] args) {
int a;
System.out.println(a);
}
如果是對(duì)象:代碼可以正常通過編譯
public static void main(String[] args) {
Date d1 = new Date();
d1.printDate();
}
通過上述例子發(fā)現(xiàn)兩個(gè)問題:
(1)?每次對(duì)象創(chuàng)建好后調(diào)用SetDate方法設(shè)置具體日期,比較麻煩,那對(duì)象該如何初始化?
(2)局部變量必須要初始化才能使用,為什么字段聲明之后沒有給值依然可以使用?
5.2 構(gòu)造方法(特殊的方法)
5.2.1 概念
構(gòu)造方法(也稱為構(gòu)造器)是一個(gè)特殊的成員方法,名字必須與類名相同,在創(chuàng)建對(duì)象時(shí),由編譯器自動(dòng)調(diào)用,并且在整個(gè)對(duì)象的生命周期內(nèi)只調(diào)用一次
class Date {
public int year;
public int month;
public int day;
//構(gòu)造方法:用于初始化
public Date(int year,int month,int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被調(diào)用了");
}
public void printDate(Date this) {
System.out.println(this.year+"/"+this.month+"/"+this.day);
}
}
注意:構(gòu)造方法的作用就是對(duì)對(duì)象中的成員進(jìn)行初始化(對(duì)象的初始化一定要調(diào)用構(gòu)造方法),并不負(fù)責(zé)給對(duì)象開辟空間
5.2.2 特性
(1)名字必須與類名相同
(2)沒有返回值類型,設(shè)置為void也不行
(3)創(chuàng)建對(duì)象時(shí)由編譯器自動(dòng)調(diào)用,并且在對(duì)象的生命周期內(nèi)只調(diào)用一次
(4)構(gòu)造方法可以重載(用戶根據(jù)自己的需求提供不同參數(shù)的構(gòu)造方法)
//帶三個(gè)參數(shù)的構(gòu)造方法:用于初始化
public Date(int year,int month,int day) {
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被調(diào)用了");
}
//無參構(gòu)造方法
public Date() {
this.year = year;
this.month = month;
this.day = day;
System.out.println("Date(int,int,int)方法被調(diào)用了");
}
(5)如果用戶沒有顯式定義,編譯器會(huì)生成一份默認(rèn)的構(gòu)造方法,生成的默認(rèn)構(gòu)造方法一定是無參的
注意:一旦用戶定義了任何一種構(gòu)造方法,編譯器則不再提供不帶參數(shù)的構(gòu)造方法,如果定義的有參數(shù),使用時(shí)卻沒傳參,編譯器會(huì)報(bào)錯(cuò)
(6)無參構(gòu)造方法中,可以通過this調(diào)用其他構(gòu)造方法來簡(jiǎn)化代碼
//無參構(gòu)造方法
public Date() {
this(1900,1,1);//但是this(1900,1,1);必須是構(gòu)造方法中第一條語句
//this.year = year;
//this.month = month;
//this.day = day;
System.out.println("Date(int,int,int)方法被調(diào)用了");
}
//三個(gè)參數(shù)的構(gòu)造方法
public Date(int year,int month,int day) {
this.year = year;
this.month = month;
this.day = day;
}
(7)Idea根據(jù)已有成員變量自動(dòng)生成定義參數(shù)個(gè)數(shù)的構(gòu)造方法:
<1>鼠標(biāo)右鍵Generate
<2>constructor
<3>ctrl選擇需要的參數(shù)
注意:
<1>this(...)必須是構(gòu)造方法中第一條語句
<2>不能形成環(huán)
public Date() {
this(1900,1,1);
}
public Date(int year,int month,int day) {
this();
}
//這兩個(gè)構(gòu)造函數(shù)不斷調(diào)用對(duì)方,形成環(huán),遞歸調(diào)用最終無法退出
(7)絕大多數(shù)情況下使用public來修飾,特殊場(chǎng)景下會(huì)被private修飾
5.3 默認(rèn)初始化
在上文中提出的第二個(gè)問題:為什么局部變量在使用時(shí)必須要初始化,而成員變量可以不用呢?
Date d = new Date(2021,6,9);
在程序?qū)用嬷皇呛?jiǎn)單的一條語句,在JVM層面需要做好多事情,下面簡(jiǎn)單介紹下:
(1)檢測(cè)對(duì)象對(duì)應(yīng)的類是否加載了,如果沒有加載則加載
(2)?為對(duì)象分配內(nèi)存空間
(3)?處理并發(fā)安全問題
比如:多個(gè)線程同時(shí)申請(qǐng)對(duì)象,JVM要保證給對(duì)象分配的空間不沖突
(4)初始化所分配的空間
即:對(duì)象空間被申請(qǐng)好之后,對(duì)象中包含的成員已經(jīng)設(shè)置好了初始值,比如:
布爾類型默認(rèn)false,引用類型默認(rèn)是null,其他類型默認(rèn)為0
?(5)設(shè)置對(duì)象頭信息
(6)?調(diào)用構(gòu)造方法,給對(duì)象中各個(gè)成員賦值
再簡(jiǎn)化就是兩步:
<1>為對(duì)象分配內(nèi)存
<2>調(diào)用合適的構(gòu)造方法
5.4 就地初始化
class Date {
public int year=1900;
public int month=1;
public int day=2;
}
注意:代碼編譯完成后,編譯器會(huì)將所有給成員初始化的這些語句添加到各個(gè)構(gòu)造函數(shù)中
本次內(nèi)容就到此啦,歡迎評(píng)論區(qū)或者私信交流,覺得筆者寫的還可以,或者自己有些許收獲的,麻煩鐵汁們動(dòng)動(dòng)小手,給俺來個(gè)一鍵三連,萬分感謝 !??文章來源:http://www.zghlxwxcb.cn/news/detail-745157.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-745157.html
到了這里,關(guān)于【JavaSE語法】類和對(duì)象(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!