繼承的出現提升了代碼的複用性,並方便開發。但隨之也有問題,有些類在描述完以後,不想被繼承,或者有些類中的部分方法功能是固定的,不想讓子類重寫。但是當子類繼承了這些特殊類以後,就能夠對其中的方法進行重寫,那怎麼解決呢?要解決上述的這些問題,須要使用到一個關鍵字final,final的意思爲最終,不可變。final是個修飾符,它能夠用來修飾類,類的成員,以及局部變量。java
final修飾類不能夠被繼承,可是能夠繼承其餘類。程序員
class Yy {} final class Fu extends Yy{} //能夠繼承Yy類 class Zi extends Fu{} //不能繼承Fu類
final修飾的方法不能夠被覆蓋,但父類中沒有被final修飾方法,子類覆蓋後能夠加final。
class Fu { // final修飾的方法,不能夠被覆蓋,但能夠繼承使用 public final void method1(){} public void method2(){} } class Zi extends Fu { //重寫method2方法 public final void method2(){} }
final修飾的變量稱爲常量,這些變量只能賦值一次。
final int i = 20; i = 30; //賦值報錯,final修飾的變量只能賦值一次
引用類型的變量值爲對象地址值,地址值不能更改,可是地址內的對象屬性值能夠修改。
final Person p = new Person(); Person p2 = new Person(); p = p2; //final修飾的變量p,所記錄的地址值不能改變 p.name = "小明";//能夠更改p對象中name屬性值 //p不能爲別的對象,而p對象中的name或age屬性值可更改。
修飾成員變量,須要在建立對象前賦值,不然報錯。(當沒有顯式賦值時,多個構造方法的均須要爲其賦值。)
class Demo { //直接賦值 final int m = 100; //final修飾的成員變量,須要在建立對象前賦值,不然報錯。 final int n; public Demo(){ //能夠在建立對象時所調用的構造方法中,爲變量n賦值 n = 2016; } }
當在定義類的時候,類中都會有相應的屬性和方法。而屬性和方法都是經過建立本類對象調用的。當在調用對象的某個方法時,這個方法沒有訪問到對象的特有數據時,方法建立這個對象有些多餘。但是不建立對象,方法又調用不了,這時就會想,那麼咱們能不能不建立對象,就能夠調用方法呢?能夠的,咱們能夠經過static關鍵字來實現。static它是靜態修飾符,通常用來修飾類中的成員。dom
被static修飾的成員變量屬於類,不屬於這個類的某個對象。(也就是說,多個對象在訪問或修改static修飾的成員變量時,其中一個對象將static成員變量值進行了修改,其餘對象中的static成員變量值跟着改變,即多個對象共享同一個static成員變量)函數
class Demo { public static int num = 100; } class Test { public static void main(String[] args) { Demo d1 = new Demo(); Demo d2 = new Demo(); d1.num = 200; System.out.println(d1.num); //結果爲200 System.out.println(d2.num); //結果爲200 } }
被static修飾的成員能夠而且建議經過類名直接訪問。訪問靜態成員的格式:this
class Demo { //靜態成員變量 public static int num = 100; //靜態方法 public static void method(){ System.out.println("靜態方法"); } } class Test { public static void main(String[] args) { System.out.println(Demo.num); Demo.method(); } }
靜態內容是優先於對象存在,只能訪問靜態,不能使用this/super。靜態修飾的內容存於靜態區。spa
class Demo { //成員變量 public int num = 100; //靜態方法 public static void method(){ //this.num; 不能使用this/super。 System.out.println(this.num); } }
同一個類中,靜態成員只能訪問靜態成員。code
class Demo { //成員變量 public int num = 100; //靜態成員變量 public static int count = 200; //靜態方法 public static void method(){ //System.out.println(num); 靜態方法中,只能訪問靜態成員變量或靜態成員方法 System.out.println(count); } }
main方法爲靜態方法僅僅爲程序執行入口,它不屬於任何一個對象,能夠定義在任意類中。對象
開發中,咱們想在類中定義一個靜態常量,一般使用public static final修飾的變量來完成定義。此時變量名用所有大寫,多個單詞使用下劃線鏈接。
定義格式: public static final 數據類型 變量名 = 值; blog
class Company { public static final String COMPANY_NAME = "百度"; public static void method(){ System.out.println("一個靜態方法"); } }
當咱們想使用類的靜態成員時,不須要建立對象,直接使用類名來訪問便可。繼承
System.out.println(Company.COMPANY_NAME); //打印百度 Company.method(); // 調用一個靜態方法
注意:
interface Inter { public static final int COUNT = 100; } //訪問接口中的靜態變量 Inter.COUNT
匿名對象是指建立對象時,只有建立對象的語句,卻沒有把對象地址值賦值給某個變量。
public class Person{ public void eat(){ System.out.println(); } } //建立一個普通對象 Person p = new Person(); //建立一個匿名對象 new Person();
匿名對象的特色:
建立匿名對象直接使用,沒有變量名。
new Person().eat() //eat方法被一個沒有名字的Person對象調用了。
匿名對象在沒有指定其引用變量時,只能使用一次。
new Person().eat(); 建立一個匿名對象,調用eat方法 new Person().eat(); 想再次調用eat方法,從新建立了一個匿名對象
匿名對象能夠做爲方法接收的參數、方法返回值使用
class Demo { public static Person getPerson(){ //普通方式 //Person p = new Person(); //return p; //匿名對象做爲方法返回值 return new Person(); } public static void method(Person p){} } class Test { public static void main(String[] args) { //調用getPerson方法,獲得一個Person對象 Person person = Demo.getPerson(); //調用method方法 Demo.method(person); //匿名對象做爲方法接收的參數 Demo.method(new Person()); } }
將類寫在其餘類的內部,能夠寫在其餘類的成員位置和局部位置,這時寫在其餘類內部的類就稱爲內部類。其餘類也稱爲外部類。
何時使用內部類?在描述事物時,若一個事物內部還包含其餘可能包含的事物,好比在描述汽車時,汽車中還包含這發動機,這時發動機就可使用內部類來描述。
class 汽車 { //外部類 class 發動機 { //內部類 } }
內部類分爲成員內部類與局部內部類。
定義內部類時,就是一個正常定義類的過程,一樣包含各類修飾符、繼承與實現關係等。在內部類中能夠直接訪問外部類的全部成員。
成員內部類,定義在外部類中的成員位置。與類中的成員變量類似,可經過外部類對象進行訪問
定義格式:
class 外部類 { 修飾符 class 內部類 { //其餘代碼 } }
訪問方式: 外部類名.內部類名 變量名 = new 外部類名().new 內部類名();
class Body {//外部類,身體 private boolean life = true; //生命狀態 public class Heart { //內部類,心臟 public void jump() { System.out.println("心臟噗通噗通的跳") System.out.println("生命狀態" + life); //訪問外部類成員變量 } } } //訪問內部類 public static void main(String[] args) { //建立內部類對象 Body.Heart bh = new Body().new Heart(); //調用內部類中的方法 bh.jump(); }
局部內部類,定義在外部類方法中的局部位置。與訪問方法中的局部變量類似,可經過調用方法進行訪問
定義格式:
class 外部類 { 修飾符 返回值類型 方法名(參數) { class 內部類 { //其餘代碼 } } }
訪問方式:在外部類方法中,建立內部類對象,進行訪問
局部內部類代碼演示
//定義類 class Party {//外部類,聚會 public void puffBall() {// 吹氣球方法 class Ball {// 內部類,氣球 public void puff() { System.out.println("氣球膨脹了"); } } //建立內部類對象,調用puff方法 new Ball().puff(); } } //訪問內部類 public static void main(String[] args) { //建立外部類對象 Party p = new Party(); //調用外部類中的puffBall方法 p.puffBall(); }
內部類是爲了應對更爲複雜的類間關係。查看源代碼中會涉及到,而在平常業務中很難遇到,這裏不作贅述。最經常使用到的內部類就是匿名內部類,它是局部內部類的一種。
定義的匿名內部類有兩個含義:
定義匿名內部類的做用與格式
做用:匿名內部類是建立某個類型子類對象的快捷方式。
格式:
new 父類或接口(){ //進行方法重寫 };
代碼演示:
//已經存在的父類: public abstract class Person{ public abstract void eat(); } //定義並建立該父類的子類對象,並用多態的方式賦值給父類引用變量 Person p = new Person(){ public void eat() { System.out.println(「我吃了」); } }; //調用eat方法 p.eat();
使用匿名對象的方式,將定義子類與建立子類對象兩個步驟由一個格式一次完成。雖然是兩個步驟,可是兩個步驟是連在一塊兒完成的。
匿名內部類若是不定義變量引用,則也是匿名對象。代碼以下:
new Person(){ public void eat() { System.out.println(「我吃了」); } }.eat();
java的包,其實就是咱們電腦系統中的文件夾,包裏存放的是類文件。當類文件不少的時候,一般咱們會採用多個包進行存放管理他們,這種方式稱爲分包管理。
在項目中,咱們將相同功能的類放到一個包中,方便管理。而且平常項目的分工也是以包做爲邊界。
類中聲明的包必須與實際class文件所在的文件夾狀況相一致,即類聲明在a包下,則生成的.class文件必須在a文件夾下,不然,程序運行時會找不到類。
一般使用公司網址反寫,能夠有多層包,包名採用所有小寫字母,多層包之間用」.」鏈接。
類中包的聲明格式: package 包名.包名.包名…;
如:黑馬程序員網址itheima.com,那麼網址反寫就爲com.itheima
注意:聲明包的語句,必須寫在程序有效代碼的第一行(註釋不算)
代碼演示:
package cn.itcast; //包的聲明,必須在有效代碼的第一行 import java.util.Scanner; import java.util.Random; public class Demo {}
在訪問類時,爲了可以找到該類,必須使用含有包名的類全名(包名.類名)。 包名.包名….類名 ,如: java.util.Scanner
帶有包的類,建立對象格式: 包名.類名 變量名 = new包名.類名(); 好比cn.itcast.Demo d = new cn.itcast.Demo();
前提:包的訪問與訪問權限密切相關,這裏以通常狀況來講,即類用public修飾的狀況。
當咱們要使用一個類時,這個類與當前程序在同一個包中(即同一個文件夾中),或者這個類是java.lang包中的類時一般能夠省略掉包名,直接使用該類。
當咱們要使用的類,與當前程序不在同一個包中(即不一樣文件夾中),要訪問的類必須用public修飾纔可訪問。
咱們每次使用類時,都須要寫很長的包名。很麻煩,咱們能夠經過import導包的方式來簡化。經過導包的方式使用該類,能夠避免使用全類名編寫(即,包類.類名)。
導包的格式: import 包名.類名;
當程序導入指定的包後,使用類時,就能夠簡化了。演示以下:
//導入包前的方式 //建立對象 java.util.Random r1 = new java.util.Random(); java.util.Random r2 = new java.util.Random(); java.util.Scanner sc1 = new java.util.Scanner(System.in); java.util.Scanner sc2 = new java.util.Scanner(System.in); //導入包後的方式 import java.util.Random; import java.util.Scanner; //建立對象 Random r1 = new Random(); Random r2 = new Random(); Scanner sc1 = new Scanner(System.in); Scanner sc2 = new Scanner(System.in);
import導包代碼書寫的位置:在聲明包package後,定義全部類class前,使用導包import包名.包名.類名;
在Java中提供了四種訪問權限,使用不一樣的訪問權限時,被修飾的內容會有不一樣的訪問權限,如下表來講明不一樣權限的訪問能力:
public |
protected |
default |
private |
|
同一類中 |
√ |
√ |
√ |
√ |
同一包中(子類與無關類) |
√ |
√ |
√ |
|
不一樣包的子類 |
√ |
√ |
|
|
不一樣包中的無關類 |
√ |
|
|
概括總結:
局部代碼塊:局部代碼塊是定義在方法或語句中。
特色:
class Demo{ public static void main(String[] args) { { int x = 1; System.out.println("普通代碼塊" + x); } int x = 99; System.out.println("代碼塊以外" + x); } }
構造代碼塊:構造代碼塊是定義在類中成員位置的代碼塊
特色:
public class Person { private String name; private int age; //構造代碼塊 { System.out.println("構造代碼塊執行了"); } Person(){ System.out.println("Person無參數的構造函數執行"); } Person(int age){ this.age = age; System.out.println("Person(age)參數的構造函數執行"); } } class PersonDemo{ public static void main(String[] args) { Person p = new Person(); Person p1 = new Person(23); } }
靜態代碼塊:靜態代碼塊是定義在成員位置,使用static修飾的代碼塊。
特色:
它優先於主方法執行、優先於構造代碼塊執行,當以任意形式第一次使用到該類時執行。
該類無論建立多少對象,靜態代碼塊只執行一次。
可用於給靜態變量賦值,用來給類進行初始化。
public class Person { private String name; private int age; //靜態代碼塊 static{ System.out.println("靜態代碼塊執行了"); } }
一、final:關鍵字,最終的意思
二、static : 關鍵字, 靜態的意思
特色:
Person.country = "中國"; Person.method();
注意事項:
三、匿名對象:一個沒有名字的對象
特色:
四、內部類:在一個類中,定義了一個新類,這個新的類就是內部類
class A {//外部類 class B{// 內部類 } }
特色: 內部類能夠直接訪問外部類的成員,包含私有的成員
五、包的聲明與訪問
類中包的聲明格式: package 包名.包名.包名…;
帶有包的類,建立對象格式:包名.類名 變量名 = new包名.類名();
六、導包的格式:import 包名.類名;
七、權限修飾符
八、代碼塊: