Java · 減熵增長(zhǎng)(第3篇)

Summary

Java是面向?qū)ο?/strong>的語(yǔ)言,應(yīng)用Java就要深入理解并掌握J(rèn)ava中類(lèi)的定義、繼承、訪問(wèn)控制、修飾符和接口等有關(guān)面向?qū)ο蟮膬?nèi)容。

  • 類(lèi)的組成、初始化和調(diào)用
  • 類(lèi)的繼承
  • 修飾符
  • 接口

類(lèi)的組成、初始化和調(diào)用

提到面向?qū)ο笳Z(yǔ)言,直接想到的是類(lèi)的概念,類(lèi)是把對(duì)象抽象出來(lái)形成一類(lèi)對(duì)象的想象,類(lèi)封裝了一類(lèi)對(duì)象的狀態(tài)和方法。類(lèi)包含fieldmethod。
field中文叫做字段、域、域變量、屬性、成員變量等,它是類(lèi)的屬性,通過(guò)變量來(lái)表示;method中文叫做方法,它是類(lèi)的功能和操作,通過(guò)函數(shù)來(lái)表示。

作者語(yǔ):類(lèi)就像現(xiàn)實(shí)物品的一個(gè)分類(lèi),比如鞋、衣服,它使得我們能夠更加高效的溝通,不僅在現(xiàn)實(shí)生活的對(duì)話中,也在編程的代碼間。
難以想象我們現(xiàn)實(shí)生活中的對(duì)話是:“請(qǐng)幫我拿一下那邊紅色的用來(lái)穿在腳上走路的物品”(請(qǐng)幫我拿下那邊紅色的鞋),所以寫(xiě)程序要用好類(lèi)的概念。

類(lèi)可以實(shí)例化,也就是建立一個(gè)具體的對(duì)象,這個(gè)時(shí)候需要初始化(通常用關(guān)鍵字new),Java是通過(guò)構(gòu)造方法constructor完成的。構(gòu)造方法和類(lèi)名是同名的,且不寫(xiě)返回值。

class Person{
  String name;
  int age;
  Person(String name, int age){
    this.name = name;
    this.age = age;
  }
}

如果類(lèi)沒(méi)有寫(xiě)構(gòu)造方法,則系統(tǒng)生成默認(rèn)構(gòu)造方法(default constructor)。

class Person{
  String name;
  int age;
  //Person(){},這是系統(tǒng)生成的默認(rèn)構(gòu)造方法,編譯時(shí)會(huì)補(bǔ)充。
}

初始化并使用對(duì)象,Person類(lèi)新建一個(gè)對(duì)象p,輸出p的名字,如下:

Person p = new Person();
System.out.println(p.name);

擴(kuò)展:
1.如果多個(gè)方法有相同的名字,編譯時(shí)可以根據(jù)方法的簽名signature(參數(shù)類(lèi)型和個(gè)數(shù))識(shí)別出,即Java有方法重載overloading的能力,體現(xiàn)了面向?qū)ο笳Z(yǔ)言的多態(tài)polymorphism。下面這段程序sayHello有兩個(gè)方法,運(yùn)行結(jié)果是:
Hello! My name is Xiaoming
Hello Xiaohong! My name is Xiaoming

public class Example{
  public static void main(String[] argv){
    Person p1 = new Person("Xiaoming", 18);
    Person p2 = new Person("Xiaohong", 14);
    p1.sayHello();
    p1.sayHello(p2);
  }
}
class Person{
  String name;
  int age;
  Person(String name, int age){
    this.name = name;
    this.age = age;
  }
  void sayHello(){
    System.out.println("Hello! My name is " + name);
  }
  void sayHello(Person another){
    System.out.println("Hello " + another.name + "! My name is " + name);
  }
}

2.在上述程序的構(gòu)造方法中出現(xiàn)了關(guān)鍵詞this,它的作用是引用字段field,添加它的目的是區(qū)分字段和局部變量。比如第一段程序構(gòu)造函數(shù)中有這樣一句代碼:this.name = name;
this.name代表Person的字段name,而等號(hào)后面的name是構(gòu)造方法的參數(shù)變量name。

類(lèi)的繼承

面向?qū)ο蟮娜蠛诵奶卣魇欠庋b、多態(tài)和繼承,在上一節(jié)中提到了封裝和多態(tài),這一節(jié)要談繼承。
說(shuō)到繼承,至少涉及兩個(gè)對(duì)象,稱為子類(lèi)subclass和父類(lèi)superclass。Java規(guī)定只能單繼承,一個(gè)類(lèi)只能有一個(gè)直接父類(lèi)。繼承符合DRY(Don't repeat yourself)原則,如果子類(lèi)有和父類(lèi)一致的字段或者方法,那么直接繼承,不要寫(xiě)重復(fù)的代碼。Java的繼承是通過(guò)關(guān)鍵詞extends來(lái)實(shí)現(xiàn)的,沿用上文Person的代碼,如下:

class Student extends Person{
  String teacher;
  int grades;
  Student(String teacher, int grades, String name, int age){
    super(name, age);
    this.teacher = teacher;
    this.grades = grades;
  }
  boolean isGood(){return grades > 80;}
}

subclass能繼承superclass的所有字段和非private方法,但不能繼承superclass的構(gòu)造方法。JDK1.5后可以用@Override標(biāo)記來(lái)表示subclass對(duì)superclass同名方法的覆蓋override。
上述程序的構(gòu)造方法中出現(xiàn)了關(guān)鍵詞super,它的作用是引用父類(lèi)的字段和方法。

作者語(yǔ):繼承是面向?qū)ο笳Z(yǔ)言中容易混亂的部分,尤其是多重繼承的時(shí)候,假設(shè)A繼承于B,B繼承于C,而C如果又繼承于A,這就是個(gè)死循環(huán)。Java單繼承的規(guī)定在一定程度上增強(qiáng)了安全性。

包package的出現(xiàn)是為了解決名字空間和名字沖突,一方面包是名字空間和存儲(chǔ)路徑,另一方面也規(guī)定了訪問(wèn)性,比如同一個(gè)包中默認(rèn)情況可互相訪問(wèn)。注:包與繼承沒(méi)有關(guān)系,一個(gè)superclass只要是public的,子類(lèi)可以在不同package中繼承superclass。
import語(yǔ)句可以導(dǎo)入包,基本語(yǔ)法是:
import package1[.package2...].classname;
例如:import java.util.Date;

作者語(yǔ):包可以理解為OS里的文件夾。

修飾符

修飾符modifier分為兩類(lèi):訪問(wèn)修飾符access modifier和其他修飾符。modifer可以修飾類(lèi)和類(lèi)的成員(field和method)。

1.訪問(wèn)修飾符

| | 同一個(gè)類(lèi)中 | 同一個(gè)包中(包括子類(lèi)) | 不同包中子類(lèi) | 不同包中非子類(lèi) |
|:--- :|:-----------:|:----------:|:-------------: |:-------------: |
|private| Yes | | | |
|默認(rèn)(包可訪問(wèn))| Yes | Yes | | |
|protected| Yes | Yes | Yes | |
|public| Yes | Yes | Yes| Yes |

private只能在同一個(gè)類(lèi)中訪問(wèn),可以更好的將信息進(jìn)行封裝和隱藏,存取時(shí)使用set和get方法;

public class Person2{
  private int age;
  public void setAge(int age){
    if(age>0 && age <150){
      this.age = age;
    }
  }
  public int getAge(){
    return age;
  }
}

默認(rèn)是class前面不加修飾符,默認(rèn)同一個(gè)包和類(lèi)可以訪問(wèn);
protected只是不允許不同包當(dāng)中的非子類(lèi)訪問(wèn);
public的作用是任何包中都可以調(diào)用。

作者語(yǔ):訪問(wèn)權(quán)限由嚴(yán)格到寬松大體流程是,從最嚴(yán)格只能在同一個(gè)類(lèi)中訪問(wèn)的private開(kāi)始,到同一個(gè)包中可以訪問(wèn)的默認(rèn)修飾,再到寬松一些可以在不同包的子類(lèi)中調(diào)用的protected修飾,最后是最寬松的在任何包中都可以調(diào)用的public修飾。

2.其他修飾符

基本含義 修飾類(lèi) 修飾成員 修飾局部變量
static 靜態(tài)的、非實(shí)例的、類(lèi)的 可以修飾內(nèi)部類(lèi) Yes
final 最終的、不可改變的 Yes Yes Yes
abstract 抽象的、非實(shí)例的 Yes Yes

static字段只屬于類(lèi),不屬于任何對(duì)象實(shí)例,例如:定義Person類(lèi),其中定義一個(gè)統(tǒng)計(jì)人數(shù)的參數(shù),并不屬于任何一個(gè)對(duì)象實(shí)例,

class Person{
  static int totalNumber;
  String name;
  int age;
  Person(String n, int a){
    name = n;
    age = a;
  }
}

static方法是屬于整個(gè)類(lèi)的方法,不屬于某個(gè)實(shí)例,不能操縱處理某個(gè)實(shí)例的成員變量;
final修飾的類(lèi)不能被繼承,也就是說(shuō)不能有子類(lèi),final修飾的方法是不能被子類(lèi)覆蓋的方法,final修飾的字段是只讀的不能修改;
abstract修飾的類(lèi)不能實(shí)例化,abstract修飾的方法是抽象方法,為所有子類(lèi)定義統(tǒng)一接口,只需聲明,格式如下:

abstarct returnType abstractMethod([paramlist]);

接口

接口interface是某種特征的約定,它也是面向?qū)ο缶幊趟枷氲暮诵慕M成部分。

作者語(yǔ):比如,我們把現(xiàn)實(shí)中的飛機(jī)寫(xiě)成一個(gè)類(lèi),其中的戰(zhàn)斗機(jī)、運(yùn)輸機(jī)都是飛機(jī)這個(gè)類(lèi)的子類(lèi),有自己的特征。戰(zhàn)斗機(jī)中,殲擊機(jī)10是殲擊機(jī)9的新一代,我們說(shuō)殲擊機(jī)10繼承了殲擊機(jī)9,在殲擊機(jī)9的動(dòng)力系統(tǒng)基礎(chǔ)上,殲擊機(jī)10開(kāi)發(fā)了應(yīng)急情況另一個(gè)加速系統(tǒng),也就是說(shuō)有兩個(gè)動(dòng)力系統(tǒng)方法,一個(gè)是繼承殲擊機(jī)9,另一個(gè)是應(yīng)急下新增加的動(dòng)力系統(tǒng),這兩個(gè)就是多態(tài)的應(yīng)用。
除了飛機(jī)外,天空中還有鳥(niǎo)。鳥(niǎo)和飛機(jī)兩個(gè)類(lèi)都會(huì)寫(xiě)一個(gè)特征——它們能夠離開(kāi)地面XX米,且有自主控制能力……本著DRY的原則,這里需要優(yōu)化,接口能很好的解決這個(gè)問(wèn)題,我們可以寫(xiě)一個(gè)特征“飛”的接口,飛機(jī)和鳥(niǎo)以及其他能飛的物體都可以使用這個(gè)接口。

根據(jù)接口的定義,它的modifier默認(rèn)是public+abstarct,因?yàn)榻涌诘某霈F(xiàn)就是要讓其他類(lèi)使用,所以默認(rèn)是public的;而接口本身就是特征的約定,不是實(shí)例化的,所以默認(rèn)是abstract的。且接口是可以多繼承的,與類(lèi)的繼承不一樣,甚至有人會(huì)說(shuō)面向?qū)ο蟮木幊虒?shí)質(zhì)上是“面向接口的變成”,可見(jiàn)接口在面向?qū)ο笳Z(yǔ)言中的重要性。

作者語(yǔ):Java規(guī)定類(lèi)是單繼承,而接口在某種程度上說(shuō)可以打破這個(gè)限制,接口不關(guān)注類(lèi)之間的層次,可以直接使用某個(gè)特征方法函數(shù)。

接口的定義一般如下:

[public] interface InterfaceName [extends listOfSuperInterface]{
  returnType methodName([paramlist]);
}

如果定義中沒(méi)有public聲明,則只能被同一個(gè)包中的類(lèi)訪問(wèn);
extends繼承部分與類(lèi)的繼承語(yǔ)法一致,不同的是接口可以多重繼承,用逗號(hào)隔開(kāi)即可;
接口中只進(jìn)行方法的聲明,不提供具體實(shí)現(xiàn),所以只有方法體,用“;”結(jié)束,這里的方法具有public和abstract屬性。
接口的實(shí)現(xiàn)用implements子句

class className implements interfaceName{
  returnType methodName([paramlist]){
    //寫(xiě)接口中所聲明方法的實(shí)現(xiàn)
  }
}

接口中定義的常量具有public, static, final的屬性,一般大寫(xiě)名字:

type NAME = value;

下面的代碼用接口定義了人

interface Runner(){public void run();}
interface Swimmer(){public void swim();}
interface Flyable(){
  abstract public void fly();
  public void land();
  public void takeoff();
}
abstract class Animal{
  int age;
  abstract public void eat();
}
class Person extends Animal implements Runner, Swimmer, Flyable{
  public void run(){System.out.println("run");}
  public void swim(){System.out.println("swim");}
  public void fly(){System.out.println("fly");}
  public void land(){System.out.println("land");}
  public void takeoff(){System.out.println("takeoff");}
  public void eat(){System.out.println("eat");}
}
public class Test{
  public static void main(String[] args){
    Test t = new Test();
    Person p =  new Person();
    t.m1(p);
    t.m2(p);
    t.m3(p);
    t.m4(p);
  }
  public void m1(Runner r){r.run();}
  public void m2(Swimmer s){s.swim();}
  public void m3(Flyable f){f.fly(); f.land(); f.takeoff();}
  public void m4(Animal a){a.eat();}
}

To be continued

Java完整的源文件格式如下:

package packageName//指定文件中的類(lèi)所在的包,0/1個(gè)
import packageName.[className]; //指定引入的類(lèi),0/多個(gè)
public class classDefinition //屬性為public的類(lèi)定義,0/1個(gè),名字必須與文件名一致
{
  [public] interface InterfaceName [extends listOfSuperInterface]//接口的定義
  {
    type constantName = value; //接口常量聲明,默認(rèn)是public, static, final的
    returnType methodName([paramlist]); //接口方法聲明,沒(méi)有方法體
  }
  [public] [abstract|final] class className [extends superClassName] [implements InterfaceNameList] //類(lèi)的聲明
  {
    [public|protected|private] [static] [final] type variableName; //成員變量聲明
    [public|protected|private] [static] [final] returnType methodName([paramlist]) [throws exceptionlist] //方法聲明及實(shí)現(xiàn)
    {
      statement;
    }
  }
}

有三種方法要求固定的聲明方式:

  • 構(gòu)造方法
className([paramlist]){
  statements;
}
  • main方法
public static void main(String[] args){
  statements;
}
  • finalize方法
protected void finalize() throw throwable{
  statements;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,679評(píng)論 18 399
  • 1.import static是Java 5增加的功能,就是將Import類(lèi)中的靜態(tài)方法,可以作為本類(lèi)的靜態(tài)方法來(lái)...
    XLsn0w閱讀 1,427評(píng)論 0 2
  • 一:java概述:1,JDK:Java Development Kit,java的開(kāi)發(fā)和運(yùn)行環(huán)境,java的開(kāi)發(fā)工...
    ZaneInTheSun閱讀 2,812評(píng)論 0 11
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,257評(píng)論 0 62
  • 轉(zhuǎn)自:http://blog.csdn.net/jackfrued/article/details/4492194...
    王帥199207閱讀 8,804評(píng)論 3 93

友情鏈接更多精彩內(nèi)容