1. 程式人生 > 實用技巧 >Java修飾符

Java修飾符

一、抽象概述

  • 不具體的,似是而非的

  • 沒有具體實現的

  • 比如Animal,只是對動物的大概描述

    • 能吃

    • 能睡

  • 具體吃啥,怎麼睡我們無從得知,創建出來的物件意義不大

  • 我們認為這種類不應該直接建立物件,應該讓其子類建立具體的物件

  • 怎麼限制?做成抽象類

    • abstract修飾的類可以變成抽象類

二、抽象類(重點)

2.1 定義

  • 被abstract修飾的類成為抽象類

  • 無法直接建立物件

  • 抽象類中可以存在抽象方法

package com.qf.abs;

public class Demo01 {
public static void main(String[] args) {
// 抽象類無法直接建立物件
// Animal animal = new Animal();
}
}

abstract class Animal{

public abstract void eat();

}

2.2 抽象類的子類和物件

  • 抽象類無法直接建立物件,但是可以有子類

  • 抽象類的子類繼承抽象類之後可以獲取到抽象類中的非私有普通屬性和方法

  • 抽象類的子類如果想使用抽象類中的抽象方法,必須重寫這些方法之後才能使用

  • 如果不使用抽象方法,做成抽象類也是可以的

package com.qf.abs;

public class Demo01 {
public static void main(String[] args) {
// 抽象類無法直接建立物件
// Animal animal = new Animal();
Husky husky = new Husky();
System.out.println(husky.type);
husky.breath();
husky.eat();

}
}

/**
* 抽象類Animal
* 描述動物的一個類
* 只做了大概的描述,沒有具體的實現
* 需要子類繼承此類後做具體的描述
* @author Dushine2008
*
*/
abstract class Animal{

// 屬性
String type = "動物";
String section;

public abstract void eat();

public abstract void sleep();

public void breath() {
System.out.println("所有的動物都依賴氧氣存活...");
}

}


abstract class Dog extends Animal{

}

class Husky extends Dog{

@Override
public void eat() {
System.out.println("二哈喜歡和主人同吃同住...");
}

@Override
public void sleep() {
System.out.println("二哈和主人同住同吃.................");
}

}

三、抽象類和多型案例(掌握)

  • 建立抽象類Car

  • 建立Car的子類

    • Auto

    • Bus

    • Tractor

  • 在子類重寫繼承的抽象方法和自己獨有的方法

  • 使用多型的思想建立物件並呼叫這些方法

package com.qf.abs;

public class Demo02 {
public static void main(String[] args) {
Car car01 = new Auto();
car01.start();
car01.stop();

// 向下轉型
Auto auto = (Auto) car01;
auto.manned();

System.out.println("========================");

Car car02 = new Bus();
car02.start();
car02.stop();

// 拆箱
Bus bus = (Bus) car02;
bus.manned();

System.out.println("========================");

Car car03 = new Tractor();
car03.start();
car03.stop();

Tractor tractor = (Tractor) car03;
tractor.doFarmWork();

}
}

/**
* 車的頂層類
* 抽象類
* 方法沒有具體的實現
* @author Dushine2008
*
*/
abstract class Car{
// 屬性
int weight;
int height;
String brand;
int price;

// 方法
public abstract void start();

public abstract void stop();
}

/**
* 奧拓車
* 繼承Car
* 重寫啟動和停止的方法
* @author Dushine2008
*
*/
class Auto extends Car{

@Override
public void start() {
System.out.println("Auto擰鑰匙啟動...");
}

@Override
public void stop() {
System.out.println("Auto這個車子剎車系統是鼓剎...");
}

public void manned() {
System.out.println("Auto這輛小車能載人5個...");
}

}

/**
* Bus類
* 繼承了Car類
* 重寫抽象方法
* @author Dushine2008
*
*/
class Bus extends Car{

@Override
public void start() {
System.out.println("Bus啟動方式很多,可以擰鑰匙,可以人力推,還可使用搖把啟動...");
}

@Override
public void stop() {
System.out.println("Bus剎車使用腳剎...");
}

public void manned() {
System.out.println("Bus載人數量能達到百人");
}

}
/**
* Tractor類
* 繼承了Car類
* 重寫抽象方法
* @author Dushine2008
*
*/
class Tractor extends Car{

@Override
public void start() {
System.out.println("Tractor早期使用搖把,後來升級了電啟動...");
}

@Override
public void stop() {
System.out.println("Tractor手扶拖拉機使用手剎,很拉風...");
}

public void doFarmWork() {
System.out.println("Tractor可以在農場裡幹活...");
}

}

四、static(重點)

4.1 定義

  • static是java中的關鍵字

  • 能修飾變數、方法、內部類

五、 靜態變數(掌握)

  • 被static修飾的變數成為靜態變數--類變數--整個類中只存在一份

  • 靜態變數被所有此類建立的物件共享,在記憶體中只存在一份

  • 在任意位置修改了這個變數,後面的物件獲取到的就是修改之後的結果

  • 推薦使用類名.屬性名呼叫

4.2.1 非靜態變數的建立和使用

package com.qf.static0;

public class Demo01 {
public static void main(String[] args) {
MyClass c01 = new MyClass();
c01.str = "我是c01中的變數str";
System.out.println(c01.str);
System.out.println(c01);

MyClass c02 = new MyClass();
c02.str = "我是c02中的變數str";
System.out.println(c02.str);
System.out.println(c02);

}
}


class MyClass{
// 屬性--例項變數--成員變數
String str;
}

4.2.2 靜態變數的建立和使用

package com.qf.static0;

public class Demo02 {
public static void main(String[] args) {
MyClass c01 = new MyClass();
c01.str = "我是c01中的變數str";
System.out.println(c01.str);
System.out.println(c01);

MyClass c02 = new MyClass();
c02.str = "我是c02中的變數str";
System.out.println(c02.str);
System.out.println(c02);

YourClass y01 = new YourClass();
YourClass.capital = "我是韓國的國都漢城";
System.out.println(YourClass.capital);
System.out.println(y01);

YourClass y02 = new YourClass();
YourClass.capital = "我是韓國的國都首爾";
System.out.println(y01.capital);
System.out.println(y02);

}
}

class YourClass{
// 被static修飾的變數成為靜態變數--類變數--整個類中只存在一份,被所有此類建立的物件共享,在記憶體中只存在一份
static String capital;
}

4.2.3 記憶體圖

4.2.4 記錄物件建立次數

package com.qf.static0;

public class Demo03 {
public static void main(String[] args) {
System.out.println(OurClass.count);

OurClass oc1 = new OurClass();
System.out.println(OurClass.count);

OurClass oc2 = new OurClass();
System.out.println(OurClass.count);

OurClass oc3 = new OurClass();
System.out.println(OurClass.count);

OurClass oc4 = new OurClass();
System.out.println(OurClass.count);
}
}

class OurClass{
// 定義靜態的變數count,記錄被執行次數
static int count = 0;

public OurClass(){
// 構造方法每一次呼叫都自增一下
count++;
}
}

class User{

}

六、靜態方法(掌握)

6.1 定義

  • static修飾的方法成為靜態方法

  • 不用建立物件就能直接呼叫

package com.qf.static0;

public class Demo04 {
public static void main(String[] args) {
// System.out.println(Integer.MIN_VALUE);
// 呼叫靜態屬性
System.out.println(MathUtil.PI);
System.out.println(MathUtil.maxInteger);
System.out.println(MathUtil.minInteger);

// 呼叫靜態方法
double abs = MathUtil.getAbs(-23.45);
System.out.println(abs);

double pow = MathUtil.getPow(3, 0);
System.out.println(pow);

}
}

class MathUtil{

// 屬性
static double PI = 3.141592653589793;
static int maxInteger = 2147483647;
static int minInteger = -2147483648;

// 方法
/**
* 獲取絕對值
* @param d
* @return
*/
public static double getAbs(double d) {
return d >= 0 ? d : -d;
}

/**
* 計算a的b次方的結果
* @param a
* @param b
* @return
*/
public static double getPow(double a,int b) {
int result = 1;
for (int i = 0; i < b; i++) {
result *= a;
}
return result;
}

}

6.2 靜態方法呼叫其他屬性和方法

  • 靜態方法呼叫靜態屬性

    • 可以

  • 靜態方法呼叫靜態方法

    • 可以

  • 靜態方法呼叫非靜態屬性

    • 不可以

  • 靜態方法呼叫非靜態方法

    • 不可以

package com.qf.static0;

public class Demo05 {
public static void main(String[] args) {

}
}


class Stu{
// 例項屬性,物件建立的時候載入到堆記憶體
String name = "張三";
// 靜態屬性,類屬性,隨著類的載入,載入的時間早於例項屬性
static int age = 23;

// 例項方法,建立物件的時候載入進記憶體,載入的時間比靜態的晚
public String getInfo() {
// 可以在非靜態方法中呼叫靜態方法和靜態變數
show();
return name + "===" + age;
}

// 靜態方法,隨著類的載入而載入,載入時間早於例項屬性,無法在此呼叫例項屬性
public static void show() {
System.out.println(age);
// 在靜態方法中只能呼叫靜態變數和靜態方法
// getInfo();
// System.out.println(name);
}
}

6.3 靜態方法、屬性的繼承

  • 子類可以獲取到父類中的例項屬性、方法

  • 子類可以獲取到父類中的靜態屬性、方法

  • 子類可以重寫父類中的例項方法

  • 子類不能重寫父類的靜態方法

package com.qf.static0;

public class Demo06 {
public static void main(String[] args) {
Man man = new Man();
man.show();
String info = man.getInfo();
System.out.println(info);

Human.type = "壯實的";
man.show();

man.type = "力氣大的";
System.out.println(Human.type);

}
}

/**
* 類Human
* 人類
* 有各種各樣的屬性和方法
* @author Dushine2008
*
*/
class Human{
// 例項屬性
String name = "李四";

// 靜態屬性,可以被繼承
static String type = "好看的";

// 例項方法
public void show() {
System.out.println("我是" + name + ",我喜歡的型別是:" + type);
}

// 靜態方法,子類可以呼叫,但是不能重寫/覆蓋
public static String getInfo() {
return "張三喜歡的型別:===" + type;
}
}

class Man extends Human{
@Override
public void show() {
System.out.println(name + ",我不僅僅喜歡===" + type);
}

/*@Override
public static String getInfo() {
return "張三喜歡的型別不僅僅是:===" + type;
}*/
}

七、程式碼塊

7.1 區域性程式碼塊(熟練)

7.1.1 定義

  • 定義在方法中的程式碼塊成為區域性程式碼塊

  • 隨著所在方法的呼叫而執行

  • 可以呼叫所在方法和類中的變數

  • 程式碼塊內部也可以定義變數,外部訪問不到

  • 適合臨時用一下的一些資料的處理

7.1.2 案例

package com.qf.block;

public class Demo01 {
static int num = 33;
public static void main(String[] args) {
int a = 110;

System.out.println("HelloWorld01");
System.out.println("HelloWorld02");

{
// 區域性程式碼塊
// 無痕瀏覽
int b = 220;
System.out.println("我是main方法中的區域性程式碼塊" + num);
}

System.out.println("HelloWorld03");
System.out.println("HelloWorld04");
System.out.println("HelloWorld05");

}
}

7.2 動態程式碼塊(構造程式碼塊)(掌握)

7.2.1 定義

  • 定義在類中的程式碼塊,位置和構造方法、例項變數同一級

  • 每一次建立物件的時候被呼叫

  • 可以完成構造方法中相同或者相似的程式碼,對構造方法進行初始化

7.2.2 案例

package com.qf.block;

public class Demo02 {
public static void main(String[] args) {

Restaurant restaurant1 = new Restaurant();
//Restaurant restaurant2 = new Restaurant("");
//Restaurant restaurant3 = new Restaurant("","");

}
}

class Restaurant{

String name;
String addr;

{
// 隨著物件的建立執行,每建立一個物件就執行一次,可以把構造方法中相同的部分寫在此處,在此完成構造方法的初始化
// 載入時間早於構造方法,載入時間和例項屬性部分先後,誰在前誰先上
System.out.println("幾位爺裡面請!!!");
System.out.println(name + "==" + addr);
}

public Restaurant() {
super();
System.out.println("空參構造方法。。。");
}

public Restaurant(String addr) {
super();
this.addr = addr;
System.out.println("1參構造方法。。。");
}

public Restaurant(String name, String addr) {
super();
this.name = name;
this.addr = addr;
System.out.println("2參構造方法。。。");
}

}

7.3 靜態程式碼塊(掌握)

7.3.1 定義

  • 使用static修飾的程式碼塊,定義在類中方法外,和變數、動態程式碼塊的位置一樣

  • 類第一次載入的時候呼叫,整個程式週期中只執行一次

  • 可以用來載入驅動等只執行一次的操作

7.3.2 案例

package com.qf.block;

public class Demo03 {
public static void main(String[] args) {
System.out.println("開始建立物件");
Mouse mouse1 = new Mouse();
Mouse mouse2 = new Mouse();
Mouse mouse3 = new Mouse();
Mouse mouse4 = new Mouse();
}
}

class Mouse{
// 屬性
String brand;
String color;

{
System.out.println("我是動態程式碼塊...");
}

static {
System.out.println("我是靜態程式碼塊================");
}

// 構造方法
public Mouse() {
super();
}

public Mouse(String brand) {
super();
this.brand = brand;
}

public Mouse(String brand, String color) {
super();
this.brand = brand;
this.color = color;
}
}

7.4 同步程式碼塊(瞭解)

  • 多執行緒中會講解