一文搞清楚Java中的包、类、接口
寫在開頭
包、類、接口、方法、變量、參數(shù)、代碼塊,這些都是構(gòu)成Java程序的核心部分,即便最簡(jiǎn)單的一段代碼里都至少要包含里面的三四個(gè)內(nèi)容,這兩天花點(diǎn)時(shí)間梳理了一下,理解又深刻了幾分。
Java中的包
Java 定義了一種名字空間,稱之為包:package。一個(gè)類總是屬于某個(gè)包,類名(比如Person)只是一個(gè)簡(jiǎn)寫,真正的完整類名是包名.類名,這才是唯一確定一個(gè)類路徑的寫法,不同包中的類名允許重復(fù)。包名推薦使用倒置的域名,例如org.apache。
包的定義
//包名
package hello;
public class Person {
// 包作用域:
public void hello() {
System.out.println("Hello!");
}
}
包的作用域
通過(guò)訪問(wèn)修飾符,可以確認(rèn)類中方法與屬性相對(duì)于包的作用域,這在前面的文章中已經(jīng)提過(guò)了,不再贅言,直接貼圖。
Java中包的引入通過(guò)import關(guān)鍵字實(shí)現(xiàn),在寫import的時(shí)候,可以使用*,表示把這個(gè)包下面的所有class都導(dǎo)入進(jìn)來(lái)(但不包括子包的class):
import java.util.ArrayList;
public class test {
public static void main(String[] args) {
ArrayList<Object> objects = new ArrayList<>();
}
}
當(dāng)然處理import導(dǎo)入外,也可以通過(guò)完成的包名.類名的方式進(jìn)行引入,但太麻煩了,很少用到。
Java中的類
Java中有個(gè)從1995年就喊出的口號(hào)“一切皆對(duì)象”,而對(duì)象在程序中的具象就是通過(guò)類(class)來(lái)實(shí)現(xiàn)!
類的創(chuàng)建
比如有這樣一個(gè)Person對(duì)象,擁有姓名,性別,年齡等特性,行為方式有吃飯,睡覺(jué)和跑步,那我們就可以在Java中如下定義:
public class Person {
//姓名
private String name;
//年齡
private int age;
//性別
private int sex;
/**
* 吃飯
*/
private void eat() {
}
/**
* 睡覺(jué)
*/
private void sleep() {
}
/**
* 跑步
*/
private void run() {
}
}
類創(chuàng)建好了,如何用呢?這時(shí)候需要通過(guò)new關(guān)鍵字去創(chuàng)建一個(gè)類對(duì)應(yīng)的對(duì)象Person person = new Person();
類的初始化賦值
這行代碼創(chuàng)建了一個(gè)Person對(duì)象,并在堆內(nèi)存中分配一定的空間,person被稱為對(duì)象Person的引用,通過(guò)這個(gè)引用可以對(duì)對(duì)象進(jìn)行初始化賦值操作
通過(guò)引用變量賦值
示例代碼:
public class Person {
private String name;
private int age;
private int sex;
public static void main(String[] args) {
Person person = new Person();
person.name = "JavaBuild";
person.age = 18;
person.sex = 1;
System.out.println(person.name);
System.out.println(person.age);
System.out.println(person.sex);
}
}
通過(guò)構(gòu)造方法賦值
示例代碼:
public class Person {
private String name;
private int age;
private int sex;
public Person(String name, int age, int sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public static void main(String[] args) {
Person person = new Person("JavaBuild", 18, 1);
System.out.println(person.name);
System.out.println(person.age);
System.out.println(person.sex);
}
}
內(nèi)部類
根據(jù)上面的內(nèi)容,我們已經(jīng)熟悉了Java中的類,實(shí)際上在類的內(nèi)部依舊可以創(chuàng)建一個(gè)類,這樣的類就被稱之為:內(nèi)部類,內(nèi)部類根據(jù)創(chuàng)建的位置,關(guān)鍵字等修飾符分為如下幾類:
1、成員內(nèi)部類
編譯之后會(huì)生成兩個(gè)class文件:OuterClass.class和OuterClass$InnerClass.class
class OuterClass {
class InnerClass {} //成員內(nèi)部類
}
2、方法內(nèi)部類
編譯之后會(huì)生成兩個(gè)class文件:OuterClass.class和OuterClass$1InnerClass.class
只能在定義該內(nèi)部類的方法內(nèi)實(shí)例化,方法內(nèi)部類對(duì)象不能使用該內(nèi)部類所在方法的非final局部變量
當(dāng)一個(gè)方法結(jié)束,其棧結(jié)構(gòu)被刪除,局部變量成為歷史。但該方法結(jié)束后,在方法內(nèi)創(chuàng)建的內(nèi)部類對(duì)象可能仍然存在于堆中
class OuterClass {
public void doSomething(){
class Inner{
}
}
}
3、匿名內(nèi)部類
編譯后生成兩個(gè)class文件:Fish.class和Fish$1.class
public class Fish {
/**
* 游泳方法
*/
public void swim() {
System.out.println("我在游泳!");
}
public static void main(String[] args) {
//創(chuàng)建魚對(duì)象
Fish fish = new Fish() {
//重寫swim方法
public void swim() {
System.out.println("我在游泳,突然發(fā)生海嘯,我撤了!");
}
};
fish.swim();
}
}
4、靜態(tài)內(nèi)部類
靜態(tài)嵌套類,并沒(méi)有對(duì)實(shí)例的共享關(guān)系,僅僅是代碼塊在外部類內(nèi)部
靜態(tài)的含義是該內(nèi)部類可以像其他靜態(tài)成員一樣,沒(méi)有外部類對(duì)象時(shí),也能夠訪問(wèn)它
靜態(tài)嵌套類僅能訪問(wèn)外部類的靜態(tài)成員和方法
在靜態(tài)方法中定義的內(nèi)部類也是靜態(tài)嵌套類,這時(shí)候不能在類前面加static關(guān)鍵字
class OuterFish {
static class InnerFish {
}
}
class TestStaticFish {
public static void main(String[] args) {
//創(chuàng)建靜態(tài)內(nèi)部類對(duì)象
OuterFish.InnerFish iFish = new OuterFish.InnerFish();
}
}
內(nèi)部類的特點(diǎn)
1、內(nèi)部類提供了某種進(jìn)入其繼承的類或?qū)崿F(xiàn)的接口的窗口
2、與外部類無(wú)關(guān),獨(dú)立繼承其他類或?qū)崿F(xiàn)接口
3、內(nèi)部類提供了Java的"多重繼承"的解決方案,彌補(bǔ)了Java類是單繼承的不足
4、內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類名和$符號(hào)
5、內(nèi)部類不能用普通的方式訪問(wèn)。內(nèi)部類是外部類的一個(gè)成員,因此內(nèi)部類可以*地訪問(wèn)外部類的成員變量,無(wú)論是否是private的
6、內(nèi)部類聲明成靜態(tài)的,就不能隨便的訪問(wèn)外部類的成員變量了,此時(shí)內(nèi)部類只能訪問(wèn)外部類的靜態(tài)成員變量
Java中的接口
在講OOP時(shí),我們提到過(guò)面向?qū)ο蟮乃拇筇匦裕渲谐橄缶褪悄莻€(gè)第四大特性,而抽象的體現(xiàn)在Java中主要為抽象類和接口!
接口是通過(guò)interface 關(guān)鍵字修飾的,用來(lái)對(duì)一類具有共性對(duì)象的一種抽象,通過(guò)不同的類進(jìn)行實(shí)現(xiàn),來(lái)滿足各自需求。
接口的特性
1、接口中允許定義變量
2、接口中允許定義抽象方法
3、接口中允許定義靜態(tài)方法(Java 8 之后)
4、接口中允許定義默認(rèn)方法(Java 8 之后)
5、接口不允許直接實(shí)例化
6、接口可以是空的
7、不要在定義接口的時(shí)候使用 final 關(guān)鍵字
8、接口的抽象方法不能是 private、protected 或者 final
9、接口的變量是隱式 public static final(常量)
接口的典型案例
我們?cè)谥傲牡綄?duì)象的淺拷貝與深拷貝時(shí)提到過(guò)Cloneable接口,這就是一個(gè)典型的接口應(yīng)用案例,Cloneable 和 Serializable 一樣,都屬于標(biāo)記型接口,它們內(nèi)部都是空的。實(shí)現(xiàn)了 Cloneable 接口的類可以使用 Object.clone() 方法,否則會(huì)拋出 CloneNotSupportedException。
接口與抽象類的區(qū)別
1、抽象類可以有構(gòu)造方法;接口中不能有構(gòu)造方法(因?yàn)椴辉试S直接實(shí)例化)。
2、抽象類中可以有普通成員變量;接口中沒(méi)有普通成員變量。
3、抽象類中可以包含非抽象普通方法;JDK1.8 以前接口中的所有方法默認(rèn)都是抽象的,JDK1.8 開始方法可以有 default 實(shí)現(xiàn)和 static 方法。
4、抽象類中的抽象方法的訪問(wèn)權(quán)限可以是 public、protected 和 default;接口中的抽象方法只能是 public 類型的,并且默認(rèn)即為 public abstract 類型。
5、抽象類中可以包含靜態(tài)方法;JDK1.8 前接口中不能包含靜態(tài)方法,JDK1.8 及以后可以包含已實(shí)現(xiàn)的靜態(tài)方法。
6、抽象類和接口中都可以包含靜態(tài)成員變量,抽象類中的靜態(tài)成員變量可以是任意訪問(wèn)權(quán)限;接口中變量默認(rèn)且只能是 public static final 類型。
7、一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,用逗號(hào)隔開,但只能繼承一個(gè)抽象類。
接口不可以實(shí)現(xiàn)接口,但可以繼承接口,并且可以繼承多個(gè)接口,用逗號(hào)隔開。
未完待續(xù)......
總結(jié)
以上是生活随笔為你收集整理的一文搞清楚Java中的包、类、接口的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何使用Markdown编写笔记
- 下一篇: Java多线程编程-(4)-线程间通信机