final、static捺典、匿名對(duì)象鸟廓,內(nèi)部類是java里面無論筆試還是面試容易被問到的關(guān)鍵詞!
final關(guān)鍵字
繼承的出現(xiàn)提高了代碼的復(fù)用性襟己,并方便開發(fā)引谜。但隨之也有問題,有些類在描述完之后擎浴,不想被繼承员咽,或者有些類中的部分方法功能是固定的,不想讓子類重寫贮预”词遥可是當(dāng)子類繼承了這些特殊類之后,就可以對(duì)其中的方法進(jìn)行重寫仿吞,那怎么解決呢滑频?要解決上述的這些問題,需要使用到一個(gè)關(guān)鍵字final唤冈,final的意思為最終误趴,不可變。final是個(gè)修飾符务傲,它可以用來修飾類凉当,類的成員枣申,以及局部變量。
final的特點(diǎn)
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; //賦值報(bào)錯(cuò),final修飾的變量只能賦值一次
引用類型的變量值為對(duì)象地址值谴供,地址值不能更改块茁,但是地址內(nèi)的對(duì)象屬性值可以修改。
final Person p = new Person();
Person p2 = new Person();
p = p2; //final修飾的變量p桂肌,所記錄的地址值不能改變
p.name = "小明";//可以更改p對(duì)象中name屬性值
//p不能為別的對(duì)象数焊,而p對(duì)象中的name或age屬性值可更改。
修飾成員變量崎场,需要在創(chuàng)建對(duì)象前賦值佩耳,否則報(bào)錯(cuò)。(當(dāng)沒有顯式賦值時(shí)谭跨,多個(gè)構(gòu)造方法的均需要為其賦值干厚。)
class Demo {
//直接賦值
final int m = 100;
//final修飾的成員變量,需要在創(chuàng)建對(duì)象前賦值螃宙,否則報(bào)錯(cuò)萍诱。
final int n;
public Demo(){
//可以在創(chuàng)建對(duì)象時(shí)所調(diào)用的構(gòu)造方法中,為變量n賦值
n = 2016;
}
}
static關(guān)鍵字
當(dāng)在定義類的時(shí)候污呼,類中都會(huì)有相應(yīng)的屬性和方法。而屬性和方法都是通過創(chuàng)建本類對(duì)象調(diào)用的包竹。當(dāng)在調(diào)用對(duì)象的某個(gè)方法時(shí)燕酷,這個(gè)方法沒有訪問到對(duì)象的特有數(shù)據(jù)時(shí),方法創(chuàng)建這個(gè)對(duì)象有些多余周瞎∶缢酰可是不創(chuàng)建對(duì)象,方法又調(diào)用不了声诸,這時(shí)就會(huì)想酱讶,那么我們能不能不創(chuàng)建對(duì)象,就可以調(diào)用方法呢彼乌?可以的泻肯,我們可以通過static關(guān)鍵字來實(shí)現(xiàn)渊迁。static它是靜態(tài)修飾符,一般用來修飾類中的成員灶挟。
static特點(diǎn)
被static修飾的成員變量屬于類琉朽,不屬于這個(gè)類的某個(gè)對(duì)象。(也就是說稚铣,多個(gè)對(duì)象在訪問或修改static修飾的成員變量時(shí)箱叁,其中一個(gè)對(duì)象將static成員變量值進(jìn)行了修改,其他對(duì)象中的static成員變量值跟著改變惕医,即多個(gè)對(duì)象共享同一個(gè)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); //結(jié)果為200
System.out.println(d2.num); //結(jié)果為200
}
}
被static修飾的成員可以并且建議通過類名直接訪問耕漱。訪問靜態(tài)成員的格式:
類名.靜態(tài)成員變量名
類名.靜態(tài)成員方法名(參數(shù))
對(duì)象名.靜態(tài)成員變量名 ------不建議使用該方式,會(huì)出現(xiàn)警告
對(duì)象名.靜態(tài)成員方法名(參數(shù)) ------不建議使用該方式抬伺,會(huì)出現(xiàn)警告
class Demo {
//靜態(tài)成員變量
public static int num = 100;
//靜態(tài)方法
public static void method(){
System.out.println("靜態(tài)方法");
}
}
class Test {
public static void main(String[] args) {
System.out.println(Demo.num);
Demo.method();
}
}
static注意事項(xiàng)
靜態(tài)內(nèi)容是優(yōu)先于對(duì)象存在螟够,只能訪問靜態(tài),不能使用this/super沛简。靜態(tài)修飾的內(nèi)容存于靜態(tài)區(qū)齐鲤。
class Demo {
//成員變量
public int num = 100;
//靜態(tài)方法
public static void method(){
//this.num; 不能使用this/super。
System.out.println(this.num);
}
}
同一個(gè)類中椒楣,靜態(tài)成員只能訪問靜態(tài)成員给郊。
class Demo {
//成員變量
public int num = 100;
//靜態(tài)成員變量
public static int count = 200;
//靜態(tài)方法
public static void method(){
//System.out.println(num); 靜態(tài)方法中,只能訪問靜態(tài)成員變量或靜態(tài)成員方法
System.out.println(count);
}
}
main方法為靜態(tài)方法僅僅為程序執(zhí)行入口捧灰,它不屬于任何一個(gè)對(duì)象淆九,可以定義在任意類中。
定義靜態(tài)常量
開發(fā)中毛俏,我們想在類中定義一個(gè)靜態(tài)常量炭庙,通常使用public static final修飾的變量來完成定義。此時(shí)變量名用全部大寫煌寇,多個(gè)單詞使用下劃線連接焕蹄。
定義格式: public static final 數(shù)據(jù)類型 變量名 = 值;
class Company {
public static final String COMPANY_NAME = "百度";
public static void method(){
System.out.println("一個(gè)靜態(tài)方法");
}
}
當(dāng)我們想使用類的靜態(tài)成員時(shí),不需要?jiǎng)?chuàng)建對(duì)象阀溶,直接使用類名來訪問即可腻脏。
System.out.println(Company.COMPANY_NAME); //打印百度
Company.method(); // 調(diào)用一個(gè)靜態(tài)方法
注意:
接口中的每個(gè)成員變量都默認(rèn)使用public static final修飾。
所有接口中的成員變量已是靜態(tài)常量银锻,由于接口沒有構(gòu)造方法永品,所以必須顯示賦值』魑常可以直接用接口名訪問鼎姐。
interface Inter {
public static final int COUNT = 100;
}
//訪問接口中的靜態(tài)變量
Inter.COUNT
匿名對(duì)象
匿名對(duì)象是指創(chuàng)建對(duì)象時(shí),只有創(chuàng)建對(duì)象的語句,卻沒有把對(duì)象地址值賦值給某個(gè)變量炕桨。
public class Person{
public void eat(){
System.out.println();
}
}
//創(chuàng)建一個(gè)普通對(duì)象
Person p = new Person();
//創(chuàng)建一個(gè)匿名對(duì)象
new Person();
匿名對(duì)象的特點(diǎn):
創(chuàng)建匿名對(duì)象直接使用饭尝,沒有變量名。
new Person().eat() //eat方法被一個(gè)沒有名字的Person對(duì)象調(diào)用了谋作。
匿名對(duì)象在沒有指定其引用變量時(shí)芋肠,只能使用一次。
new Person().eat(); 創(chuàng)建一個(gè)匿名對(duì)象遵蚜,調(diào)用eat方法
new Person().eat(); 想再次調(diào)用eat方法帖池,重新創(chuàng)建了一個(gè)匿名對(duì)象
匿名對(duì)象可以作為方法接收的參數(shù)、方法返回值使用
class Demo {
public static Person getPerson(){
//普通方式
//Person p = new Person();
//return p;
//匿名對(duì)象作為方法返回值
return new Person();
}
public static void method(Person p){}
}
class Test {
public static void main(String[] args) {
//調(diào)用getPerson方法吭净,得到一個(gè)Person對(duì)象
Person person = Demo.getPerson();
//調(diào)用method方法
Demo.method(person);
//匿名對(duì)象作為方法接收的參數(shù)
Demo.method(new Person());
}
}
內(nèi)部類
將類寫在其他類的內(nèi)部睡汹,可以寫在其他類的成員位置和局部位置,這時(shí)寫在其他類內(nèi)部的類就稱為內(nèi)部類寂殉。其他類也稱為外部類囚巴。
什么時(shí)候使用內(nèi)部類?在描述事物時(shí),若一個(gè)事物內(nèi)部還包含其他可能包含的事物友扰,比如在描述汽車時(shí)彤叉,汽車中還包含這發(fā)動(dòng)機(jī),這時(shí)發(fā)動(dòng)機(jī)就可以使用內(nèi)部類來描述村怪。
class 汽車 { //外部類
class 發(fā)動(dòng)機(jī) { //內(nèi)部類
}
}
內(nèi)部類的分類
內(nèi)部類分為成員內(nèi)部類與局部?jī)?nèi)部類秽浇。
定義內(nèi)部類時(shí),就是一個(gè)正常定義類的過程甚负,同樣包含各種修飾符柬焕、繼承與實(shí)現(xiàn)關(guān)系等。在內(nèi)部類中可以直接訪問外部類的所有成員梭域。
成員內(nèi)部類斑举,定義在外部類中的成員位置。與類中的成員變量相似病涨,可通過外部類對(duì)象進(jìn)行訪問
定義格式:
class 外部類 {
修飾符 class 內(nèi)部類 {
//其他代碼
}
}
訪問方式: 外部類名.內(nèi)部類名 變量名 = new 外部類名().new 內(nèi)部類名();
class Body {//外部類富玷,身體
private boolean life = true; //生命狀態(tài)
public class Heart { //內(nèi)部類,心臟
public void jump() {
System.out.println("心臟噗通噗通的跳")
System.out.println("生命狀態(tài)" + life); //訪問外部類成員變量
}
}
}
//訪問內(nèi)部類
public static void main(String[] args) {
//創(chuàng)建內(nèi)部類對(duì)象
Body.Heart bh = new Body().new Heart();
//調(diào)用內(nèi)部類中的方法
bh.jump();
}
局部?jī)?nèi)部類既穆,定義在外部類方法中的局部位置赎懦。與訪問方法中的局部變量相似,可通過調(diào)用方法進(jìn)行訪問
定義格式:
class 外部類 {
修飾符 返回值類型 方法名(參數(shù)) {
class 內(nèi)部類 {
//其他代碼
}
}
}
訪問方式:在外部類方法中循衰,創(chuàng)建內(nèi)部類對(duì)象,進(jìn)行訪問
局部?jī)?nèi)部類代碼演示
//定義類
class Party {//外部類褐澎,聚會(huì)
public void puffBall() {// 吹氣球方法
class Ball {// 內(nèi)部類会钝,氣球
public void puff() {
System.out.println("氣球膨脹了");
}
}
//創(chuàng)建內(nèi)部類對(duì)象,調(diào)用puff方法
new Ball().puff();
}
}
//訪問內(nèi)部類
public static void main(String[] args) {
//創(chuàng)建外部類對(duì)象
Party p = new Party();
//調(diào)用外部類中的puffBall方法
p.puffBall();
}
內(nèi)部類的實(shí)際使用——匿名內(nèi)部類
內(nèi)部類是為了應(yīng)對(duì)更為復(fù)雜的類間關(guān)系。查看源代碼中會(huì)涉及到迁酸,而在日常業(yè)務(wù)中很難遇到先鱼,這里不做贅述。最常用到的內(nèi)部類就是匿名內(nèi)部類奸鬓,它是局部?jī)?nèi)部類的一種焙畔。
定義的匿名內(nèi)部類有兩個(gè)含義:
臨時(shí)定義某一指定類型的子類
定義后即刻創(chuàng)建剛剛定義的這個(gè)子類的對(duì)象
定義匿名內(nèi)部類的作用與格式
作用:匿名內(nèi)部類是創(chuàng)建某個(gè)類型子類對(duì)象的快捷方式。
格式:
new 父類或接口(){
//進(jìn)行方法重寫
};
代碼演示:
//已經(jīng)存在的父類:
public abstract class Person{
public abstract void eat();
}
//定義并創(chuàng)建該父類的子類對(duì)象串远,并用多態(tài)的方式賦值給父類引用變量
Person p = new Person(){
public void eat() {
System.out.println(“我吃了”);
}
};
//調(diào)用eat方法
p.eat();
使用匿名對(duì)象的方式宏多,將定義子類與創(chuàng)建子類對(duì)象兩個(gè)步驟由一個(gè)格式一次完成。雖然是兩個(gè)步驟澡罚,但是兩個(gè)步驟是連在一起完成的伸但。
匿名內(nèi)部類如果不定義變量引用,則也是匿名對(duì)象留搔。代碼如下:
new Person(){
public void eat() {
System.out.println(“我吃了”);
}
}.eat();
包的聲明與訪問
java的包更胖,其實(shí)就是我們電腦系統(tǒng)中的文件夾,包里存放的是類文件隔显。當(dāng)類文件很多的時(shí)候却妨,通常我們會(huì)采用多個(gè)包進(jìn)行存放管理他們,這種方式稱為分包管理括眠。
在項(xiàng)目中彪标,我們將相同功能的類放到一個(gè)包中,方便管理哺窄。并且日常項(xiàng)目的分工也是以包作為邊界捐下。
類中聲明的包必須與實(shí)際class文件所在的文件夾情況相一致,即類聲明在a包下萌业,則生成的.class文件必須在a文件夾下坷襟,否則,程序運(yùn)行時(shí)會(huì)找不到類生年。
包的聲明格式
通常使用公司網(wǎng)址反寫婴程,可以有多層包,包名采用全部小寫字母抱婉,多層包之間用”.”連接档叔。
類中包的聲明格式: package 包名.包名.包名…;
如:黑馬程序員網(wǎng)址itheima.com,那么網(wǎng)址反寫就為com.itheima
注意:聲明包的語句蒸绩,必須寫在程序有效代碼的第一行(注釋不算)
代碼演示:
package cn.itcast; //包的聲明衙四,必須在有效代碼的第一行
import java.util.Scanner;
import java.util.Random;
public class Demo {}
包的訪問
在訪問類時(shí),為了能夠找到該類患亿,必須使用含有包名的類全名(包名.類名)传蹈。 包名.包名….類名 押逼,如: java.util.Scanner
帶有包的類,創(chuàng)建對(duì)象格式: 包名.類名 變量名 = new包名.類名(); 比如cn.itcast.Demo d = new cn.itcast.Demo();
前提:包的訪問與訪問權(quán)限密切相關(guān)惦界,這里以一般情況來說挑格,即類用public修飾的情況。
類的簡(jiǎn)化訪問
當(dāng)我們要使用一個(gè)類時(shí)沾歪,這個(gè)類與當(dāng)前程序在同一個(gè)包中(即同一個(gè)文件夾中)漂彤,或者這個(gè)類是java.lang包中的類時(shí)通常可以省略掉包名灾搏,直接使用該類挫望。
當(dāng)我們要使用的類,與當(dāng)前程序不在同一個(gè)包中(即不同文件夾中)确镊,要訪問的類必須用public修飾才可訪問士骤。
import導(dǎo)包
我們每次使用類時(shí),都需要寫很長(zhǎng)的包名蕾域。很麻煩拷肌,我們可以通過import導(dǎo)包的方式來簡(jiǎn)化。通過導(dǎo)包的方式使用該類旨巷,可以避免使用全類名編寫(即巨缘,包類.類名)。
導(dǎo)包的格式: import 包名.類名;
當(dāng)程序?qū)胫付ǖ陌蟛赡牛褂妙悤r(shí)若锁,就可以簡(jiǎn)化了。演示如下:
//導(dǎo)入包前的方式
//創(chuàng)建對(duì)象
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);
//導(dǎo)入包后的方式
import java.util.Random;
import java.util.Scanner;
//創(chuàng)建對(duì)象
Random r1 = new Random();
Random r2 = new Random();
Scanner sc1 = new Scanner(System.in);
Scanner sc2 = new Scanner(System.in);
import導(dǎo)包代碼書寫的位置:在聲明包package后斧吐,定義所有類class前又固,使用導(dǎo)包import包名.包名.類名;
訪問修飾符
在Java中提供了四種訪問權(quán)限,使用不同的訪問權(quán)限時(shí)煤率,被修飾的內(nèi)容會(huì)有不同的訪問權(quán)限仰冠,以下表來說明不同權(quán)限的訪問能力:
四種權(quán)限訪問表
歸納總結(jié):
要想僅能在本類中訪問使用private修飾;
要想本包中的類都可以訪問不加修飾符即可蝶糯;
要想本包中的類與其他包中的子類可以訪問使用protected修飾
要想所有包中的所有類都可以訪問使用public修飾洋只。
注意:如果類用public修飾,則類名必須與文件名相同昼捍。一個(gè)文件中只能有一個(gè)public修飾的類识虚。
代碼塊
局部代碼塊:局部代碼塊是定義在方法或語句中。
特點(diǎn):
以”{}”劃定的代碼區(qū)域妒茬,此時(shí)只需要關(guān)注作用域的不同即可
方法和類都是以代碼塊的方式劃定邊界的
class Demo{
public static void main(String[] args) {
{
int x = 1;
System.out.println("普通代碼塊" + x);
}
int x = 99;
System.out.println("代碼塊之外" + x);
}
}
構(gòu)造代碼塊:構(gòu)造代碼塊是定義在類中成員位置的代碼塊
特點(diǎn):
優(yōu)先于構(gòu)造方法執(zhí)行担锤,構(gòu)造代碼塊用于執(zhí)行所有對(duì)象均需要的初始化動(dòng)作
每創(chuàng)建一個(gè)對(duì)象均會(huì)執(zhí)行一次構(gòu)造代碼塊。
public class Person {
private String name;
private int age;
//構(gòu)造代碼塊
{
System.out.println("構(gòu)造代碼塊執(zhí)行了");
}
Person(){
System.out.println("Person無參數(shù)的構(gòu)造函數(shù)執(zhí)行");
}
Person(int age){
this.age = age;
System.out.println("Person(age)參數(shù)的構(gòu)造函數(shù)執(zhí)行");
}
}
class PersonDemo{
public static void main(String[] args) {
Person p = new Person();
Person p1 = new Person(23);
}
}
靜態(tài)代碼塊:靜態(tài)代碼塊是定義在成員位置乍钻,使用static修飾的代碼塊肛循。
特點(diǎn):
它優(yōu)先于主方法執(zhí)行蛛株、優(yōu)先于構(gòu)造代碼塊執(zhí)行,當(dāng)以任意形式第一次使用到該類時(shí)執(zhí)行育拨。
該類不管創(chuàng)建多少對(duì)象,靜態(tài)代碼塊只執(zhí)行一次欢摄。
可用于給靜態(tài)變量賦值熬丧,用來給類進(jìn)行初始化。
public class Person {
private String name;
private int age;
//靜態(tài)代碼塊
static{
System.out.println("靜態(tài)代碼塊執(zhí)行了");
}
}
知識(shí)點(diǎn)總結(jié)
1怀挠、final:關(guān)鍵字析蝴,最終的意思
final修飾的類:最終的類,不能被繼承
final修飾的變量: 相當(dāng)于是一個(gè)常量, 在編譯生產(chǎn).class文件后绿淋,該變量變?yōu)槌A恐?/p>
final修飾的方法: 最終的方法闷畸,子類不能重寫,可以繼承過來使用
2吞滞、static : 關(guān)鍵字佑菩, 靜態(tài)的意思
可以用來修飾類中的成員(成員變量,成員方法)
也可以用來修飾成員內(nèi)部類
特點(diǎn):
被靜態(tài)所修飾的成員裁赠,會(huì)被所有的對(duì)象所共享
被靜態(tài)所修飾的成員殿漠,可以通過類名直接調(diào)用,方便
Person.country = "中國";
Person.method();
注意事項(xiàng):
靜態(tài)的成員佩捞,隨著類的加載而加載绞幌,優(yōu)先于對(duì)象存在
在靜態(tài)方法中,沒有this關(guān)鍵字
靜態(tài)方法中一忱,只能調(diào)用靜態(tài)的成員(靜態(tài)成員變量莲蜘,靜態(tài)成員方法
3、匿名對(duì)象:一個(gè)沒有名字的對(duì)象
特點(diǎn):
創(chuàng)建匿名對(duì)象直接使用帘营,沒有變量名
匿名對(duì)象在沒有指定其引用變量時(shí)票渠,只能使用一次
匿名對(duì)象可以作為方法接收的參數(shù)、方法返回值使用
4仪吧、內(nèi)部類:在一個(gè)類中庄新,定義了一個(gè)新類,這個(gè)新的類就是內(nèi)部類
class A {//外部類
class B{// 內(nèi)部類
}
}
特點(diǎn): 內(nèi)部類可以直接訪問外部類的成員薯鼠,包含私有的成員
5择诈、包的聲明與訪問
類中包的聲明格式: package 包名.包名.包名…;
帶有包的類,創(chuàng)建對(duì)象格式:包名.類名 變量名 = new包名.類名();
6出皇、導(dǎo)包的格式:import 包名.類名;
7羞芍、權(quán)限修飾符
public : 公共的
protected: 受保護(hù)的
private : 私有的
public protected 默認(rèn)的 private
8、代碼塊:
局部代碼塊:定義在方法中的郊艘,用來限制變量的作用范圍
構(gòu)造代碼塊:定義在類中方法外荷科,用來給對(duì)象中的成員初始化賦值
靜態(tài)代碼塊:定義在類中方法外唯咬,用來給類的靜態(tài)成員初始化賦值
(更多相關(guān)java知識(shí)干貨,關(guān)注“軟帝在線”公眾號(hào)獲取相關(guān)福利)