final
final 不可改變刻诊,可以用于修飾類防楷、方法、變量
- 類 :被修飾的類则涯,不能被繼承
- 方法:被修飾的方法复局, 不能被重寫
- 變量:被修飾的變量冲簿、不能被重新賦值
使用
- 修飾類
格式如下:
final class 類名 {
}
像 String、Math亿昏、Scanner這些類都是被final修飾峦剔,目的是供我們呢使用,而不讓我們修改角钩。
- 修飾方法
格式:
修飾符 final 返回值類型 方法名(參數(shù)列表){
// 方法體
}
如果重寫final修飾的方法吝沫,編譯會(huì)報(bào)錯(cuò)
- 修飾變量
- 局部變量--基本類型
基本類型的局部變量,被final修飾后递礼, 只能賦值一次惨险,不能再改
public static void main(String[] args) {
// 聲明一個(gè)變量,被final修飾
final int a;
a = 10;
// a = 20; 不可以
final int b = 20;
// b = 20; 不可以
}
下面哪個(gè)可以通過(guò)編譯
寫法一:
final int c = 0;
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ì)報(bào)錯(cuò)脊髓, 寫法二會(huì)通過(guò)編譯辫愉, 因?yàn)槊看窝h(huán), 都是一個(gè)新的c
- 局部變量--引用類型
引用類型的局部變量被final修飾后只能指向一個(gè)對(duì)象将硝, 但是不影響對(duì)象內(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(); 報(bào)錯(cuò)指向了新的對(duì)象,地址值改變
u.userName = "張三"; // 可以對(duì)象內(nèi)部修改成員變量
System.out.println(u.userName);
}
}
- 成員變量
成員變量涉及到初始化問(wèn)題依疼,初始化有兩種痰腮, 只能選一個(gè)
- 顯示初始化
public class User {
// 顯示初始化
final String USERNAME = "張三";
}
被final修飾的常量名稱, 一般字母都大寫
構(gòu)造方法初始化
public class User {
final String USERNAME;
private int age;
public User(String username, int age) {
this.USERNAME = username;
this.age = age;
}
}
權(quán)限修飾符
不同的訪問(wèn)權(quán)限修飾符修飾時(shí)涛贯, 被修飾的內(nèi)容會(huì)有不同的訪問(wèn)權(quán)限
- public 公有的
- protected 受保護(hù)的
- default 默認(rèn)的
-
private 私有的
可見(jiàn)public 具有最大權(quán)限诽嘉,private 最小權(quán)限
建議使用權(quán)限: - 成員變量使用
private
, 隱藏細(xì)節(jié) - 構(gòu)造方法使用
public
弟翘,方便創(chuàng)建對(duì)象 - 成員方法使用
public
虫腋, 方便調(diào)用
不加權(quán)限修飾符, 其訪問(wèn)能力與default相同
內(nèi)部類
將類A定義在另一個(gè)類B中稀余,里面的類A就是內(nèi)部類悦冀, B是外部類
- 成員內(nèi)部類 :定義在類中方法外的類
格式:
class 外部類{
class 內(nèi)部類{
}
}
在描述事物時(shí), 若一個(gè)事物內(nèi)部還包含其他事物睛琳,就可以使用內(nèi)部類這種結(jié)構(gòu)盒蟆, 比如Car中包含Engine, Engine就可以使用內(nèi)部類來(lái)描述
class Car{
class Engine{
}
}
訪問(wèn)特點(diǎn)
- 內(nèi)部類可以直接訪問(wèn)外部類的成員师骗, 包括私有成員历等。
- 外部類要訪問(wèn)內(nèi)部類成員,必須要建立內(nèi)部類對(duì)象
創(chuàng)建內(nèi)部類對(duì)象的格式
外部類名.內(nèi)部類名 對(duì)象名 = new 外部類型().new 內(nèi)部類型()辟癌;
匿名內(nèi)部類
匿名內(nèi)部類: 是內(nèi)部類的簡(jiǎn)化寫法寒屯,它本質(zhì)是一個(gè)帶具體實(shí)現(xiàn)的父類或者父接口的匿名子類對(duì)象。開發(fā)中, 最常用到的內(nèi)部類就是匿名內(nèi)部類
以接口為例寡夹,當(dāng)你使用一個(gè)接口時(shí)处面, 似乎需要如下幾步:
- 定義子類
- 重寫接口中所有的方法
- 創(chuàng)建子類對(duì)象
- 調(diào)用重寫后的方法
我們的目的是調(diào)用方法, 那能否簡(jiǎn)化一下呢菩掏?將四個(gè)步驟合為一步呢魂角?
匿名內(nèi)部類就可以實(shí)現(xiàn)
前提
匿名內(nèi)部類必須繼承一個(gè)父類或者實(shí)現(xiàn)一個(gè)父接口
格式
new 父類名或父接口(){
// 方法重寫
@ Override
public void method(){
// 執(zhí)行語(yǔ)句
}
}
public abstract class FlyAble {
public abstract void fly();
}
public class InnerDemo {
public static void main(String[] args) {
/**
* 等號(hào)左邊:是多態(tài)賦值, (抽象類)接口類型引用指向子類對(duì)象
* 等號(hào)右邊:是匿名內(nèi)部類智绸, 定義并創(chuàng)建該接口的子類對(duì)象
*/
FlyAble f = new FlyAble() {
@Override
public void fly() {
System.out.println("嗷嗷飛");
}
};
System.out.println(f);
f.fly();
}
}
通常在方法的形參是接口或者抽象的時(shí)候野揪, 也可以講匿名內(nèi)部類作為參數(shù)傳遞
public class InnerDemo {
public static void main(String[] args) {
/**
* 等號(hào)左邊:是多態(tài)賦值, (抽象類)接口類型引用指向子類對(duì)象
* 等號(hào)右邊:是匿名內(nèi)部類传于, 定義并創(chuàng)建該接口的子類對(duì)象
*/
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();
}
}
簡(jiǎn)化
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()+"點(diǎn)傷害");
}
// 防御
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()+"點(diǎn)傷害");
}
// 防御
public void wear(){
// 增加防御
this.blood += ar.getProtect();
System.out.println("穿上了" + ar.getName()+", 生命值增加了" + ar.getProtect());
}
}
類作為成員變量系草, 對(duì)它進(jìn)行賦值操作, 實(shí)際上唆涝, 是賦給他該類的對(duì)象
接口作為成員變量
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ā)動(dòng)法術(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();
}
}
接口作為成員變量找都, 對(duì)它進(jìn)行賦值操作, 實(shí)際上賦給他該接口的子類的對(duì)象
接口作為方法的參數(shù)和返回值類型
當(dāng)接口作為方法的參數(shù)和返回值類型廊酣,傳遞和返回的都是他的子類對(duì)象
原來(lái)我們這樣做
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ù)時(shí)能耻, 他傳遞的是子類對(duì)象
接口作為返回值類型是, 他返回的是子類對(duì)象