我們都說java是面向物件的程式語言,那什麼是面向物件呢?什麼是類呢?什麼是方法呢?
類、物件、方法
類是物件的抽象定義,物件是類的具體例項。
類:指的是一類東西,比如汽車,人類,書等這些都指的是一類東西或物品。
物件:指類的具體的實體,比如一輛汽車,一本書等,我們要記住一切皆物件(東西)。
同時物件具有狀態(屬性)和行為(方法)
我以人為例:
人屬性有:臉,手,腳,鼻子,耳朵,身高,性別,鼻子,耳朵等屬性
人的行為(方法):吃,喝,跑,睡覺等。
這幾個大家都能理解吧,而java中是如何建立類和物件的呢
先建立一個學生類(這些都是學生的屬性和方法)
public class Student {
String name; //姓名
int age; //年齡
String classNo; //班級
String hobby; //愛好
public void chi(){
System.out.println(name+"吃飯了")
}
//輸出資訊方法
public void show(){
System.out.println(name + "\n年齡:" + age + "\n就讀於:" +classNo + "\n愛好:" + hobby);
}
}
這樣就建立好一個類了,那如何建立一個物件呢。
首先舉一個例子:小李設計了一張汽車設計圖,然後交給生產車間來生產汽車,有黑色的、紅色的、白色的... 這裡,汽車設計圖就是我們說的類(class),生產車間就是new構造器(大部分物件都是new出來的),生產出來的汽車就是我們要說的物件。可以說java程式設計實質就是構建類的過程。
public class InitialStudent {
public static void main(String args[]){
Student student = new Student(); //建立物件
student.name = "小明"; //給物件賦值
student.age = 10;
student.classNo = "S1班";
student.hobby = "籃球";
student.chi();
student.show(); //呼叫方法
}
}
到現在我都是以自己的組織的語言給大家講解,為的是讓大家能夠理解,那麼java程式設計的規範有哪些,它的具體的細節又有哪些下面我就具體講一下
類的定義
類必須先定義才能使用。類是建立物件的模板,建立物件也叫類的例項化。(類是物件的抽象定義,物件是類的具體例項)類實質上是一個數據型別。
例子:
public class Dog
{
String name;
int age;
void bark()//汪汪叫
{
System.out.println("汪汪,不要過來");
}
void hungry()
{
System.out.println("主人,我餓了");
}
}
對示例的說明:
- public 是類的修飾符,表明該類是公共類,可以被其他類訪問。
-
一個類儲存到一個檔案中,並且檔名要與類名相同。(一個檔案中可以執行多個類宣告,只能有一個類是public,檔名必須和該類類名一致)
-
class 是定義類的關鍵字。
-
Dog是類的名稱。
- name,age是類的成員變數,也叫屬性;bark(),hungry()是類中的函式,也叫方法。
-
物件例項化: 類名 物件名 = new 類名(); //未例項化的物件不能訪問其屬性和方法
-
訪問屬性:物件名.屬性名
-
訪問方法:物件名.方法名(引數列表)
作用域修飾詞
1、public:public表明該資料成員、成員函式是對所有使用者開放的,所有使用者都可以直接進行呼叫
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有財產神聖不可侵犯嘛,即便是子女,朋友,都不可以使用。
3、protected:protected對於子女、朋友來說,就是public的,可以自由使用,沒有任何限制,而對於其他的外部class,protected就變成private。
作用域 | 當前類 | 同一package | 子孫類 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
friendly(預設) | √ | √ | × | × |
private | √ | × | × | × |
一個類可以包含以下型別變數:
-
區域性變數:在方法或者語句塊中定義的變數被稱為區域性變數。變數宣告和初始化都是在方法中,方法結束後,變數就會自動銷燬。
-
成員變數:成員變數是定義在類中,方法體之外的變數。這種變數在建立物件的時候例項化(分配記憶體)。成員變數可以被類中的方法和特定類的語句訪問。
-
類變數:類變數也宣告在類中,方法體之外,但必須宣告為static型別。static也是修飾符的一種。
同時類也可以被final修飾,下面將會講解finnal關鍵字和static關鍵字
比較 | 成員變數 | 區域性變數 |
---|---|---|
作用域 | 整個類中起作用(包括方法中) | 只在方法中起作用 |
初始值 | byte,short,int,long型是0 float,double型是0.0 char型是’\0’ boolean型是false |
沒有初始值,無法使用 |
注:當局部變數與成員變數重名時,在方法中優先使用區域性變數,方法中使用成員變數使用this,this代表當前類的當前物件。
static(靜態)
類的靜態成員不依賴類的某一例項,可使用類名直接訪問
1.靜態變數(類變數)
當類第一次被載入(任何一個物件的宣告,首先要載入類),該類的靜態變數就分配獨立記憶體,直到程式結束被回收。靜態成員是公共的。(區域性變數不能用static修飾)
比較 | 靜態變數 | 成員變數 |
---|---|---|
作用域 | 當前類 | 當前類 |
生命週期 | 類載入到程式結束 | 從物件產生到物件回收 |
使用方法 | 類名.靜態變數名 | 物件名.成員變數名 |
靜態變數即類變數 成員變數即例項變數,物件例項化後才能使用
靜態方法
- 訪問靜態方法:類名.方法名(引數列表)
靜態方法在同一個類中被呼叫時,類名可以省略。普通成員方法必須在物件例項化後才可以呼叫
比較 | 靜態方法 | 成員方法 |
---|---|---|
呼叫 | 類名.方法名(引數) | 物件名.方法名(引數) |
呼叫普通方法 | 不能直接呼叫 | 同一個類中可以呼叫 |
呼叫靜態方法 | 類名.方法名(引數) | 類名.方法名(引數) |
訪問靜態變數 | 類名.靜態變數名 | 類名.靜態變數名 |
訪問成員變數 | 不能直接訪問 | 同一類中可以直接訪問 |
this關鍵字 | 不能使用 | 可以使用 |
static程式碼塊
static關鍵字還有一個比較關鍵的作用就是 用來形成靜態程式碼塊以優化程式效能。static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被載入的時候,會按照static塊的順序來執行每個static塊,並且只會在類載入的時候執行一次。
一般用來載入靜態資源比如載入圖片,視訊,音訊等。
final
Java關鍵字final有“這是無法改變的”或者“終態的”含義,它可以修飾非抽象類、非抽象類成員方法和變數。
1.修飾類
當用final修飾一個類時,表明這個類不能被繼承。也就是說,如果一個類你永遠不會讓他被繼承,就可以用final進行修飾。final類中的成員變數可以根據需要設為final,但是要注意final類中的所有成員方法都會被隱式地指定為final方法。
注:在使用final修飾類的時候,要注意謹慎選擇,除非這個類真的在以後不會用來繼承或者出於安全的考慮,儘量不要將類設計為final類。
修飾方法
使用final方法的原因有兩個。
第一個原因是把方法鎖定,以防任何繼承類修改它的含義;
第二個原因是效率。在早期的Java實現版本中,會將final方法轉為內嵌呼叫。但是如果方法過於龐大,可能看不到內嵌呼叫帶來的任何效能提升。在最近的Java版本中,不需要使用final方法進行這些優化了。
注:類的private方法會隱式地被指定為final方法。
修飾變數
修飾變數是final用得最多的地方,也是重點闡述的內容
對於一個final變數,
如果是基本資料型別的變數,則其數值一旦在初始化之後便不能更改;
如果是引用型別的變數,則在對其初始化之後便不能再讓其指向另一個物件。
- 類的final變數和普通變數有什麼區別
- 當用final作用於類的成員變數時,成員變數(注意是類的成員變數,區域性變數只需要保證在使用之前被初始化賦值即可)必須在定義時或者構造器中進行初始化賦值,而且final變數一旦被初始化賦值之後,就不能再被賦值了。
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b + 2;
String e = d + 2;
System.out.println((a == c));//true
System.out.println((a == e));//false
}
}
分析
為什麼第一個比較結果為true,而第二個比較結果為fasle。這裡面就是final變數和普通變數的區別了,當final變數是基本資料型別以及String型別時,如果在編譯期間能知道它的確切值,則編譯器會把它當做編譯期常量使用。也就是說在用到該final變數的地方,相當於直接訪問的這個常量,不需要在執行時確定。這種和C語言中的巨集替換有點像。因此在上面的一段程式碼中,由於變數b被final修飾,因此會被當做編譯器常量,所以在使用到b的地方會直接將變數b 替換為它的 值。而對於變數d的訪問卻需要在執行時通過連結來進行。想必其中的區別大家應該明白了,不過要注意,只有在編譯期間能確切知道final變數值的情況下,編譯器才會進行這樣的優化,比如下面的這段程式碼就不會進行優化:
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = getHello();
String c = b + 2;
System.out.println((a == c));//這段程式碼的輸出結果為false。
}
public static String getHello() {
return "hello";
}
}
- 被final修飾的引用變數指向的物件內容可變嗎
- 引用變數被final修飾之後,雖然不能再指向其他物件,但是它指向的物件的內容是可變的。
public class Test {
public static void main(String[] args) {
final MyClass myClass = new MyClass();
System.out.println(++myClass.i);//結果為1
}
}
class MyClass {
public int i = 0;
}
- final引數的問題
- 無論引數是基本資料型別的變數還是引用型別的變數,使用final宣告都不會防止你無意的修改而影響到呼叫方法外的變數
public class Test {
public static void main(String[] args) {
MyClass myClass = new MyClass();
StringBuffer buffer = new StringBuffer("hello");
myClass.changeValue(buffer);
System.out.println(buffer.toString());
}
}
class MyClass {
void changeValue(final StringBuffer buffer) {
buffer.append("world");
}
}
執行這段程式碼就會發現輸出結果為 helloworld。很顯然,用final進行修飾並沒有阻止在changeValue中改變buffer指向的物件的內容。有人說假如把final去掉了,萬一在changeValue中讓buffer指向了其他物件怎麼辦。有這種想法的朋友可以自己動手寫程式碼試一下這樣的結果是什麼,如果把final去掉了,然後在changeValue中讓buffer指向了其他物件,也不會影響到main方法中的buffer,原因在於java採用的是值傳遞,對於引用變數,傳遞的是引用的值,也就是說讓實參和形參同時指向了同一個物件,因此讓形參重新指向另一個物件對實參並沒有任何影響。
static final
-
static作用於成員變數用來表示只儲存一份副本,而final的作用是用來保證變數不可變。
-
static final修飾的屬性表示一旦給值,就不可修改,並且可以通過類名訪問。
-
static final也可以修飾方法,表示該方法不能重寫,可以在不new物件的情況下呼叫。
方法
- 為什麼要有方法
- 提高程式碼的複用性
- 什麼是方法
- 完成特定功能的程式碼塊。
-
方法的格式
修飾符 返回值型別 方法名(引數型別 引數名1,引數型別 引數名2...) {
方法體語句;
return 返回值;
}
- 方法的格式說明
- 修飾符:一般就用 public,static,final。
- 返回值型別:就是功能結果的資料型別。
- 方法名:符合命名規則即可。方便我們的呼叫。
- 引數:
- 實際引數:就是實際參與運算的。
- 形式引數;就是方法定義上的,用於接收實際引數的。
- 引數型別:就是引數的資料型別
- 引數名:就是變數名
- 方法體語句:就是完成功能的程式碼。
- return:結束方法的。
- 返回值:就是功能的結果,由return帶給呼叫者。
構造方法(特殊的方法)
在類例項化的過程中自動執行的方法叫做構造方法,它不需要你手動呼叫。構造方法可以在類例項化的過程中做一些初始化的工作。
構造方法的名稱必須與類的名稱相同,並且沒有返回值。
每個類都有構造方法。如果沒有顯式地為類定義構造方法,Java編譯器將會為該類提供一個預設的構造方法。
public class Dog
{
String name;
int age;
//構造方法,沒有返回值
Dog(String name1,int age1)
{
name = name1;
age = age1;
System.out.println("感謝主人領養了我");
}
//普通方法,必須有返回值
void bark()
{
System.out.println("汪汪,不要過來");
}
void hungry()
{
System.out.println("主人,我餓了");
}
public static void main(String[] args)
{
//建立物件時傳遞的引數要與構造方法引數列表對應
Dog myDog = new Dog("花花",3);
}
}
執行結果:
感謝主人領養了我
package day23;
/*構造方法
- 作用是用於初始化引數
- 所有的數字變數全部設定為0
- 所有的boolean型別全部設定為false
- 所有的物件變數全部設定為null
*/
/*
- 設計自己的構造方法
- 方法名稱必須和類的名稱相同
- 沒有返回值
*/
/*
- 如果自己寫了有參的構造方法,那麼編譯器不會再提供
- 預設的構造方法了
- 如果我們還想用無參的構造方法,
- 那麼需要手動實現
*/
public class People
{
String name;
String sex;
int age;
//無參的構造方法(可以不寫編譯器自動加上,前提是沒有任何其他構造方法)
People()//構造方法(可刪掉,編譯器預設加上)
{
// name = null;
// sex = null;
// age = 0;
}
//有參的構造方法
People(String name,String sex,int age)
{
this.name = name;
this.sex = sex;
this.age = age;
}
//部分初始化
People(String name)
{
this.name = name;
}
People(String name,int age)
{
this.name = name;
this.age = age;
}
public static void main(String[] args)
{
People p = new People();
System.out.println(p.name);
System.out.println(p.sex);
System.out.println(p.age);
People p1 = new People("張三","男",30);
System.out.println(p1.name+","+p1.sex+","+p1.age);
People p2 = new People("老王");
System.out.println(p2.name);
People p3 = new People("小老虎",3);
System.out.println(p3.name+","+p2.age);
}
}
說明:
-
構造方法不能被顯式呼叫。
-
構造方法不能有返回值,因為沒有變數來接收返回值
建立物件
物件是類的一個例項,建立物件的過程也叫類的例項化。物件是以類為模板來建立的。
在Java中,使用new關鍵字來建立物件,一般有以下三個步驟:
-
宣告:宣告一個物件,包括物件名稱和物件型別
-
例項化:使用關鍵字new來建立一個物件。
-
初始化:使用new建立物件時,會呼叫構造方法初始化物件。
例如:
Dog myDog;//宣告一個物件
myDog = new Dog("花花",3);//例項化
也可以在宣告的同時進行初始化:
Dog myDog = new Dog("花花",3);
訪問成員變數和方法
通過已建立的物件來訪問成員變數和成員方法,例如:
//例項化
Dog myDog = new Dog("花花",3);
//通過點號訪問成員變數
myDog.name;
//通過點號訪問成員方法
myDog.bark();
下面的例子演示瞭如何訪問成員變數和方法:
public class Dog
{
String name;
int age;
Dog(String name1,int age1)
{
name = name1;
age = age1;
System.out.println("感謝主人領養了我");
}
void bark()
{
System.out.println("汪汪,不要過來");
}
void hungry()
{
System.out.println("主人,我餓了");
}
public static void main(String[] args)
{
Dog myDog = new Dog("花花",3);
//訪問成員變數
String name = myDog.name;
int age = myDog.age;
System.out.println("我是一隻小狗,我名字叫" + name + ",我" + age + "歲了");
//訪問方法
myDog.bark();
myDog.hungry();
}
}
執行結果:
感謝主人領養了我
我是一隻小狗,我名字叫花花,我3歲了
汪汪,不要過來
主人,我餓了