final
final不可改變寇漫,可以用于修飾類、方法殉摔、變量
- 類:被修飾的類州胳,不能被繼承
- 方法:被修飾的方法,不能被重寫
- 變量:被修飾的變量逸月,不能被重新賦值
使用
-
修飾類
格式如下:
final class 類名{
}
像String栓撞、math、Scanner這些類都是被final修飾
-
修飾方法
格式
修飾符 final 返回值類型 方法名 (參數(shù)列表){ //方法體 }
如果重寫final修飾的方法碗硬,編譯會報錯
- 修飾變量
- 局部變量-基本類型
基本類型的局部變量瓤湘,被final修飾后,只能賦值一次恩尾,不能再改
public static void main(String[] args) {
// 聲明一個變量岭粤,被final修飾
final int a;
a = 10;
// a = 20; 不可以
final int b = 20;
// b = 20; 不可以
}
下面哪個會報錯,哪個會通過編譯
寫法一
final int c = i;
for (int i = 0; i < 10; i++) {
c = i;
System.out.println(c);
}
寫法二:
for (int i = 0; i < 10; i++) {
final int c = i;
System.out.println(c);
}
寫法一會報錯特笋,寫法二會通過編譯,因為每次循環(huán)巾兆,都是一個新的c
- 局部變量--引用類型
引用類型的局部變量被final修飾后只能指向一個對象猎物,但是不影響對象內(nèi)部的成員變量值的修改。
public static void main(String[] args) {
final User u = new User();
// User u = new User();
System.out.println(u);
// u = new User();
System.out.println(u);
// u = new User(); 報錯指向了新的對象角塑,地址值改變
u.userName = "張三"; // 可以對象內(nèi)部修改成員變量
System.out.println(u.userName);
}
}
- 成員變量
成員變量涉及到初始化問題蔫磨,初始化有兩種,只能選一個
- 顯式初始化
public class User {
//顯示初始化
final String USERNAME = "張三";
}
- 構(gòu)造方法初始化
public class User {
// 構(gòu)造方法初始化
final String USERNAME ;
private int age;
public User(String username, int age) {
USERNAME = username;
this.age = age;
}
}
權(quán)限修飾符
不同的訪問權(quán)限修飾符修飾時圃伶,被修飾的內(nèi)容會有不同的訪問權(quán)限
- public 共有的
- protected 受保護的
- default 默認的
- private 私有的
[圖片上傳失敗...(image-219cf-1595674734317)]
可見public 具有最大權(quán)限堤如,private 最小權(quán)限
建議使用權(quán)限:
- 成員變量使用private 蒲列, 隱藏細節(jié)
- 構(gòu)造方法使用public,方便創(chuàng)建對象
- 成員方法使用public搀罢, 方便調(diào)用
不加權(quán)限修飾符蝗岖, 其訪問能力與default相同
內(nèi)部類
將類A定義在另一個類B中,里面的類A就是內(nèi)部類榔至, B是外部類
- 成員內(nèi)部類 :定義在類中方法外的類
格式:
class 外部類{
class 內(nèi)部類{
}
}
在描述事物時抵赢, 若一個事物內(nèi)部還包含其他事物,就可以使用內(nèi)部類這種結(jié)構(gòu)唧取, 比如Car中包含Engine铅鲤, Engine就可以使用內(nèi)部類來描述
class Car{
class Engine{
}
}
訪問特點
- 內(nèi)部類可以直接訪問外部類的成員, 包括私有成員枫弟。
- 外部類要訪問內(nèi)部類成員邢享,必須要建立內(nèi)部類對象
創(chuàng)建內(nèi)部類對象的格式
外部類名.內(nèi)部類名 對象名 = new 外部類型().new 內(nèi)部類型();
匿名內(nèi)部類
匿名內(nèi)部類: 是內(nèi)部類的簡化寫法淡诗,它本質(zhì)是一個帶具體實現(xiàn)的父類或者父接口的匿名子類對象骇塘。開發(fā)中, 最常用到的內(nèi)部類就是匿名內(nèi)部類
以接口為例袜漩,當你使用一個接口時绪爸, 似乎需要如下幾步:
- 定義子類
- 重寫接口中所有的方法
- 創(chuàng)建子類對象
- 調(diào)用重寫后的方法
我們的目的是調(diào)用方法, 那能否簡化一下呢宙攻?將四個步驟合為一步呢奠货?
匿名內(nèi)部類就可以實現(xiàn)
前提
匿名內(nèi)部類必須繼承一個父類或者實現(xiàn)一個父接口
格式
new 父類名或父接口(){
// 方法重寫
@ Override
public void method(){
// 執(zhí)行語句
}
}
public abstract class FlyAble {
public abstract void fly();
}
public class InnerDemo {
public static void main(String[] args) {
/**
* 等號左邊:是多態(tài)賦值, (抽象類)接口類型引用指向子類對象
* 等號右邊:是匿名內(nèi)部類座掘, 定義并創(chuàng)建該接口的子類對象
*/
FlyAble f = new FlyAble() {
@Override
public void fly() {
System.out.println("嗷嗷飛");
}
};
System.out.println(f);
f.fly();
}
}
通常在方法的形參是接口或者抽象的時候递惋, 也可以講匿名內(nèi)部類作為參數(shù)傳遞
public class InnerDemo {
public static void main(String[] args) {
/**
* 等號左邊:是多態(tài)賦值, (抽象類)接口類型引用指向子類對象
* 等號右邊:是匿名內(nèi)部類溢陪, 定義并創(chuàng)建該接口的子類對象
*/
FlyAble f = new FlyAble() {
@Override
public void fly() {
System.out.println("嗷嗷飛");
}
};
System.out.println(f);
showFly(f);
}
public static void showFly(FlyAble flyAble){
flyAble.fly();
}
}
簡化
package com.neusoft.day11.InnerClassDemo2;
/**
* @author Eric Lee
* @date 2020/7/25 11:14
*/
public class InnerDemo2 {
public static void main(String[] args) {
showFly(new FlyAble() {
@Override
public void fly() {
System.out.println("嗷嗷飛");
}
});
}
public static void showFly(FlyAble flyAble){
flyAble.fly();
}
}
引用類型用法總結(jié)
- 基本類型可以作為成員變量萍虽、方法參數(shù)、方法返回值形真,引用也是可以的
class作為成員變量
package com.neusoft.day11.classMember;
/**
* @author Eric Lee
* @date 2020/7/25 11:43
*/
public class Weapon {
String name;
int hurt; // 傷害
public Weapon(String name, int hurt) {
this.name = name;
this.hurt = hurt;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHurt() {
return hurt;
}
public void setHurt(int hurt) {
this.hurt = hurt;
}
}
package com.neusoft.day11.classMember;
/**
* @author Eric Lee
* @date 2020/7/25 11:44
*/
public class Armour {
//
String name;
int protect; // 防御值
public Armour(String name, int protect) {
this.name = name;
this.protect = protect;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getProtect() {
return protect;
}
public void setProtect(int protect) {
this.protect = protect;
}
}
package com.neusoft.day11.classMember;
/**
* @author Eric Lee
* @date 2020/7/25 11:42
*/
public class Role {
int id ;
int blood ; // 生命值
String name;
// 添加武器屬性
Weapon wp;
// 盔甲
Armour ar;
public Weapon getWp() {
return wp;
}
public void setWp(Weapon wp) {
this.wp = wp;
}
public Armour getAr() {
return ar;
}
public void setAr(Armour ar) {
this.ar = ar;
}
// 攻擊
public void attack(){
System.out.println("使用"+ wp.getName() + "杉编, 造成了" + wp.getHurt()+"點傷害");
}
// 防御
public void wear(){
// 增加防御
this.blood += ar.getProtect();
System.out.println("穿上了" + ar.getName()+", 生命值增加了" + ar.getProtect());
}
}
package com.neusoft.day11.classMember;
/**
* @author Eric Lee
* @date 2020/7/25 11:42
*/
public class Role {
int id ;
int blood ; // 生命值
String name;
// 添加武器屬性
Weapon wp;
// 盔甲
Armour ar;
public Weapon getWp() {
return wp;
}
public void setWp(Weapon wp) {
this.wp = wp;
}
public Armour getAr() {
return ar;
}
public void setAr(Armour ar) {
this.ar = ar;
}
// 攻擊
public void attack(){
System.out.println("使用"+ wp.getName() + ", 造成了" + wp.getHurt()+"點傷害");
}
// 防御
public void wear(){
// 增加防御
this.blood += ar.getProtect();
System.out.println("穿上了" + ar.getName()+", 生命值增加了" + ar.getProtect());
}
}
類作為成員變量咆霜, 對它進行賦值操作邓馒, 實際上, 是賦給他該類的對象
接口作為成員變量
public interface FaShuSkill {
public abstract void faShuAttack();
}
public class WangZheRole {
FaShuSkill fs;
public void setFaShuSkill(FaShuSkill fs) {
this.fs = fs;
}
// 法術(shù)攻擊
public void faShuSkillAttack(){
System.out.println("發(fā)動法術(shù)攻擊");
fs.faShuAttack();
System.out.println("攻擊完畢");
}
}
package com.neusoft.day11.classMember;
/**
* @author Eric Lee
* @date 2020/7/25 14:26
*/
public class WangZheTest {
public static void main(String[] args) {
WangZheRole role = new WangZheRole();
// role.setName("zhangsan")
role.setFaShuSkill(new FaShuSkill() {
@Override
public void faShuAttack() {
System.out.println("安琪拉的羊肉串");
}
});
// 法術(shù)攻擊
role.faShuSkillAttack();
// 更換技能
role.setFaShuSkill(new FaShuSkill() {
@Override
public void faShuAttack() {
System.out.println("大喬叫你回家");
}
});
// 法術(shù)攻擊
role.faShuSkillAttack();
}
}
接口作為成員變量蛾坯, 對它進行賦值操作光酣, 實際上賦給他該接口的子類的對象
接口作為方法的參數(shù)和返回值類型
當接口作為方法的參數(shù)和返回值類型,傳遞和返回的都是他的子類對象
原來我們這樣做
public class Demo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
ArrayList<Integer> doubleNumList = getDoubleNum(list);
System.out.println(doubleNumList);
}
public static ArrayList<Integer> getDoubleNum(ArrayList<Integer> list){
ArrayList<Integer> doubleList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i) % 2 == 0)
doubleList.add(list.get(i));
}
return doubleList;
}
}
接口作為方法的參數(shù)和返回值類型, 我們這樣做
package com.neusoft.day11.interfaceDemo;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eric Lee
* @date 2020/7/25 14:37
*/
public class Demo1 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
List<Integer> doubleNumList = getDoubleNum(list);
System.out.println(doubleNumList);
}
public static List<Integer> getDoubleNum(List<Integer> list){
List<Integer> doubleList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if (list.get(i) % 2 == 0)
doubleList.add(list.get(i));
}
return doubleList;
}
}
接口作為參數(shù)時脉课, 他傳遞的是子類對象
接口作為返回值類型是救军, 他返回的是子類對象