Java面向對象(static、final、匿名對象、內部類、包、修飾符、代碼塊)
面向對象
今日內容介紹
u final
u static
u 匿名對象
u 內部類
u 包的聲明與訪問
u 四種訪問修飾符
u 代碼塊
第1章 final關鍵字
1.1 final的概念
繼承的出現提高了代碼的復用性,並方便開發。但隨之也有問題,有些類在描述完之後,不想被繼承,或者有些類中的部分方法功能是固定的,不想讓子類重寫。可是當子類繼承了這些特殊類之後,就可以對其中的方法進行重寫,那怎麽解決呢?
要解決上述的這些問題,需要使用到一個關鍵字final,final的意思為最終,不可變。final是個修飾符,它可以用來修飾類,類的成員,以及局部變量。
1.2 final的特點
l final修飾類不可以被繼承,但是可以繼承其他類。
class Yy {}
final class Fu extends Yy{} //可以繼承Yy類
class Zi extends Fu{} //不能繼承Fu類
l final修飾的方法不可以被覆蓋,但父類中沒有被final修飾方法,子類覆蓋後可以加final。
class Fu {
// final修飾的方法,不可以被覆蓋,但可以繼承使用
public final void method1(){}
public void method2(){}
}
class Zi extends Fu {
//重寫method2方法
public final void method2(){}
}
l final修飾的變量稱為常量,這些變量只能賦值一次。
final int i = 20;
i = 30; //賦值報錯,final修飾的變量只能賦值一次
l 引用類型的變量值為對象地址值,地址值不能更改,但是地址內的對象屬性值可以修改。
final Person p = new Person();
Person p2 = new Person();
p = p2; //final修飾的變量p,所記錄的地址值不能改變
p.name = "小明";//可以更改p對象中name屬性值
p不能為別的對象,而p對象中的name或age屬性值可更改。
l 修飾成員變量,需要在創建對象前賦值,否則報錯。(當沒有顯式賦值時,多個構造方法的均需要為其賦值。)
class Demo {
//直接賦值
final int m = 100;
//final修飾的成員變量,需要在創建對象前賦值,否則報錯。
final int n;
public Demo(){
//可以在創建對象時所調用的構造方法中,為變量n賦值
n = 2016;
}
}
第2章 static關鍵字
2.1 static概念
當在定義類的時候,類中都會有相應的屬性和方法。而屬性和方法都是通過創建本類對象調用的。當在調用對象的某個方法時,這個方法沒有訪問到對象的特有數據時,方法創建這個對象有些多余。可是不創建對象,方法又調用不了,這時就會想,那麽我們能不能不創建對象,就可以調用方法呢?
可以的,我們可以通過static關鍵字來實現。static它是靜態修飾符,一般用來修飾類中的成員。
2.2 static特點
l 被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
}
}
l 被static修飾的成員可以並且建議通過類名直接訪問。
訪問靜態成員的格式:
類名.靜態成員變量名
類名.靜態成員方法名(參數)
對象名.靜態成員變量名 ------不建議使用該方式,會出現警告
對象名.靜態成員方法名(參數) ------不建議使用該方式,會出現警告
代碼演示:
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();
}
}
2.3 static註意事項
l 靜態內容是優先於對象存在,只能訪問靜態,不能使用this/super。靜態修飾的內容存於靜態區。
class Demo {
//成員變量
public int num = 100;
//靜態方法
public static void method(){
//this.num; 不能使用this/super。
System.out.println(this.num);
}
}
l 同一個類中,靜態成員只能訪問靜態成員
class Demo {
//成員變量
public int num = 100;
//靜態成員變量
public static int count = 200;
//靜態方法
public static void method(){
//System.out.println(num); 靜態方法中,只能訪問靜態成員變量或靜態成員方法
System.out.println(count);
}
}
l main方法為靜態方法僅僅為程序執行入口,它不屬於任何一個對象,可以定義在任意類中。
2.4 定義靜態常量
開發中,我們想在類中定義一個靜態常量,通常使用public static final修飾的變量來完成定義。此時變量名用全部大寫,多個單詞使用下劃線連接。
定義格式:
public static final 數據類型 變量名 = 值;
如下演示:
class Company {
public static final String COMPANY_NAME = "傳智播客";
public static void method(){
System.out.println("一個靜態方法");
}
}
當我們想使用類的靜態成員時,不需要創建對象,直接使用類名來訪問即可。
System.out.println(Company.COMPANY_NAME); //打印傳智播客
Company.method(); // 調用一個靜態方法
l 註意:
接口中的每個成員變量都默認使用public static final修飾。
所有接口中的成員變量已是靜態常量,由於接口沒有構造方法,所以必須顯示賦值。可以直接用接口名訪問。
interface Inter {
public static final int COUNT = 100;
}
訪問接口中的靜態變量
Inter.COUNT
第3章 匿名對象
3.1 匿名對象的概念
匿名對象是指創建對象時,只有創建對象的語句,卻沒有把對象地址值賦值給某個變量。
如:已經存在的類:
public class Person{
public void eat(){
System.out.println();
}
}
創建一個普通對象
Person p = new Person();
創建一個匿名對象
new Person();
3.2 匿名對象的特點
l 創建匿名對象直接使用,沒有變量名。
new Person().eat() //eat方法被一個沒有名字的Person對象調用了。
l 匿名對象在沒有指定其引用變量時,只能使用一次。
new Person().eat(); 創建一個匿名對象,調用eat方法
new Person().eat(); 想再次調用eat方法,重新創建了一個匿名對象
l 匿名對象可以作為方法接收的參數、方法返回值使用
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());
}
}
第4章 內部類
4.1 內部類概念
l 什麽是內部類
將類寫在其他類的內部,可以寫在其他類的成員位置和局部位置,這時寫在其他類內部的類就稱為內部類。其他類也稱為外部類。
l 什麽時候使用內部類
在描述事物時,若一個事物內部還包含其他可能包含的事物,比如在描述汽車時,汽車中還包含這發動機,這時發動機就可以使用內部類來描述。
class 汽車 { //外部類
class 發動機 { //內部類
}
}
l 內部類的分類
內部類分為成員內部類與局部內部類。
我們定義內部類時,就是一個正常定義類的過程,同樣包含各種修飾符、繼承與實現關系等。在內部類中可以直接訪問外部類的所有成員。
4.2 成員內部類
成員內部類,定義在外部類中的成員位置。與類中的成員變量相似,可通過外部類對象進行訪問
l 定義格式
class 外部類 {
修飾符 class 內部類 {
//其他代碼
}
}
l 訪問方式
外部類名.內部類名 變量名 = new 外部類名().new 內部類名();
l 成員內部類代碼演示
定義類
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();
}
4.3 局部內部類
局部內部類,定義在外部類方法中的局部位置。與訪問方法中的局部變量相似,可通過調用方法進行訪問
l 定義格式
class 外部類 {
修飾符 返回值類型 方法名(參數) {
class 內部類 {
//其他代碼
}
}
}
l 訪問方式
在外部類方法中,創建內部類對象,進行訪問
l 局部內部類代碼演示
定義類
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();
}
4.4 內部類的實際使用——匿名內部類
4.4.1 匿名內部類概念
內部類是為了應對更為復雜的類間關系。查看源代碼中會涉及到,而在日常業務中很難遇到,這裏不做贅述。
最常用到的內部類就是匿名內部類,它是局部內部類的一種。
定義的匿名內部類有兩個含義:
l 臨時定義某一指定類型的子類
l 定義後即刻創建剛剛定義的這個子類的對象
4.4.2 定義匿名內部類的作用與格式
作用:匿名內部類是創建某個類型子類對象的快捷方式。
格式:
new 父類或接口(){
//進行方法重寫
};
l 代碼演示
//已經存在的父類:
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();
第5章 包的聲明與訪問
5.1 包的概念
java的包,其實就是我們電腦系統中的文件夾,包裏存放的是類文件。
當類文件很多的時候,通常我們會采用多個包進行存放管理他們,這種方式稱為分包管理。
在項目中,我們將相同功能的類放到一個包中,方便管理。並且日常項目的分工也是以包作為邊界。
類中聲明的包必須與實際class文件所在的文件夾情況相一致,即類聲明在a包下,則生成的.class文件必須在a文件夾下,否則,程序運行時會找不到類。
5.2 包的聲明格式
通常使用公司網址反寫,可以有多層包,包名采用全部小寫字母,多層包之間用”.”連接
類中包的聲明格式:
package 包名.包名.包名…;
如:黑馬程序員網址itheima.com那麽網址反寫就為com.itheima
傳智播客 itcast.cn 那麽網址反寫就為 cn.itcast
l 註意:聲明包的語句,必須寫在程序有效代碼的第一行(註釋不算)
l 代碼演示:
package cn.itcast; //包的聲明,必須在有效代碼的第一行
import java.util.Scanner;
import java.util.Random;
public class Demo {}
5.3 包的訪問
在訪問類時,為了能夠找到該類,必須使用含有包名的類全名(包名.類名)。
包名.包名….類名
如: java.util.Scanner
java.util.Random
cn.itcast.Demo
帶有包的類,創建對象格式:包名.類名 變量名 = new包名.類名();
cn.itcast.Demo d = new cn.itcast.Demo();
l 前提:包的訪問與訪問權限密切相關,這裏以一般情況來說,即類用public修飾的情況。
l 類的簡化訪問
當我們要使用一個類時,這個類與當前程序在同一個包中(即同一個文件夾中),或者這個類是java.lang包中的類時通常可以省略掉包名,直接使用該類。
如:cn.itcast包中有兩個類,PersonTest類,與Person類。我們在PersonTest類中,訪問Person類時,由於是同一個包下,訪問時可以省略包名,即直接通過類名訪問 Person。
類名 變量名 = new類名();
Person p = new Person();
l 當我們要使用的類,與當前程序不在同一個包中(即不同文件夾中),要訪問的類必須用public修飾才可訪問。
package cn.itcst02;
public class Person {}
5.4 import導包
我們每次使用類時,都需要寫很長的包名。很麻煩,我們可以通過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);
l import導包代碼書寫的位置:在聲明包package後,定義所有類class前,使用導包import包名.包名.類名;
第6章 訪問修飾符
在Java中提供了四種訪問權限,使用不同的訪問權限時,被修飾的內容會有不同的訪問權限,以下表來說明不同權限的訪問能力:
|
public |
protected |
default |
private |
同一類中 |
√ |
√ |
√ |
√ |
同一包中(子類與無關類) |
√ |
√ |
√ |
|
不同包的子類 |
√ |
√ |
|
|
不同包中的無關類 |
√ |
|
|
|
歸納一下:在日常開發過程中,編寫的類、方法、成員變量的訪問
l 要想僅能在本類中訪問使用private修飾;
l 要想本包中的類都可以訪問不加修飾符即可;
l 要想本包中的類與其他包中的子類可以訪問使用protected修飾
l 要想所有包中的所有類都可以訪問使用public修飾。
l 註意:如果類用public修飾,則類名必須與文件名相同。一個文件中只能有一個public修飾的類。
第7章 代碼塊
7.1 局部代碼塊
局部代碼塊是定義在方法或語句中
特點:
l 以”{}”劃定的代碼區域,此時只需要關註作用域的不同即可
l 方法和類都是以代碼塊的方式劃定邊界的
class Demo{
public static void main(String[] args) {
{
int x = 1;
System.out.println("普通代碼塊" + x);
}
int x = 99;
System.out.println("代碼塊之外" + x);
}
}
結果:
普通代碼塊1
代碼塊之外99
7.2 構造代碼塊
構造代碼塊是定義在類中成員位置的代碼塊
特點:
l 優先於構造方法執行,構造代碼塊用於執行所有對象均需要的初始化動作
l 每創建一個對象均會執行一次構造代碼塊。
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);
}
}
7.3 靜態代碼塊
靜態代碼塊是定義在成員位置,使用static修飾的代碼塊。
特點:
l 它優先於主方法執行、優先於構造代碼塊執行,當以任意形式第一次使用到該類時執行。
l 該類不管創建多少對象,靜態代碼塊只執行一次。
l 可用於給靜態變量賦值,用來給類進行初始化。
public class Person {
private String name;
private int age;
//靜態代碼塊
static{
System.out.println("靜態代碼塊執行了");
}
}
第8章 總結
8.1 知識點總結
l final:關鍵字,最終的意思
final修飾的類:最終的類,不能被繼承
final修飾的變量: 相當於是一個常量, 在編譯生產.class文件後,該變量變為常量值
final修飾的方法: 最終的方法,子類不能重寫,可以繼承過來使用
l static : 關鍵字, 靜態的意思
可以用來修飾類中的成員(成員變量,成員方法)
註意: 也可以用來修飾成員內部類
l 特點:
被靜態所修飾的成員,會被所有的對象所共享
被靜態所修飾的成員,可以通過類名直接調用,方便
Person.country = "中國";
Person.method();
l 註意事項:
靜態的成員,隨著類的加載而加載,優先於對象存在
在靜態方法中,沒有this關鍵字
靜態方法中,只能調用靜態的成員(靜態成員變量,靜態成員方法
l 匿名對象:一個沒有名字的對象
l 特點:
創建匿名對象直接使用,沒有變量名
匿名對象在沒有指定其引用變量時,只能使用一次
匿名對象可以作為方法接收的參數、方法返回值使用
l 內部類:在一個類中,定義了一個新類,這個新的類就是內部類
class A {//外部類
class B{// 內部類
}
}
l 特點:
內部類可以直接訪問外部類的成員,包含私有的成員
l 包的聲明與訪問
l 類中包的聲明格式:
package 包名.包名.包名…;
l 帶有包的類,創建對象格式:包名.類名 變量名 = new包名.類名();
cn.itcast.Demo d = new cn.itcast.Demo();
l 導包的格式:
import 包名.類名;
l 權限修飾符
public : 公共的
protected: 受保護的
private : 私有的
public protected 默認的 private
在當前類中 Y Y Y Y
同一包中的其他類 Y Y Y
不同包中的子類 Y Y
不同包中的其他類 Y
l 代碼塊:
局部代碼塊:定義在方法中的,用來限制變量的作用範圍
構造代碼塊:定義在類中方法外,用來給對象中的成員初始化賦值
靜態代碼塊:定義在類中方法外,用來給類的靜態成員初始化賦值
Java面向對象(static、final、匿名對象、內部類、包、修飾符、代碼塊)