目錄
- 類
- 對象
- 構造方法
- 引用與對象實例
- static
- final
- 封裝
- 繼承
- 方法重載與重寫
- 多態
- 抽象類
- 接口
- 內部類
Java是面向對象的高級語言,類和對象是Java程序的核心。
類和對象
當我們買一部手機時,需要的是內存大一點、運行速度快一點、像素高一點等等,它是對象麼?
不是,它是一個類。
當我們買了一部華爲時,它就是一個對象。對象是具體的、確定的物體。
這部手機的顏色、尺寸、編號等是它的屬性;我們使用手機來打電話、發短信的行爲是它的“方法”。
-
創建類
類,是具有相同屬性和方法的對象的集合。public class 類名{ // 屬性(成員變量) 屬性類型1 屬性命1; ... // 方法 方法1; ...
一個類可以包含以下類型變量:
局部變量:在方法、構造方法或者語句塊中定義的變量被稱爲局部變量。變量聲明和初始化都是在方法中,方法結束後,變量就會自動銷燬。
成員變量:成員變量是定義在類中,方法體之外的變量。這種變量在創建對象的時候實例化。成員變量可以被類中方法、構造方法和特定類的語句塊訪問。
類變量:也叫靜態變量,類變量也聲明在類中,方法體之外,但必須聲明爲 static 類型。 -
創建對象
創建類時,不會開闢內存進行存儲。當創建對象時,纔開闢內存存儲屬性和方法。類名 對象名 = new 類名();
// Test.java public class Test{ // 屬性(成員變量) double height; int age; int sex; // 性別,0爲男;非0爲女 // 方法 void laugh(){ System.out.println("我有笑"); } void printBaseMes(){ System.out.println("我的身高是:" + height); System.out.println("年齡:" + age); if (this.sex == 0){ System.out.println("男"); } else{ System.out.println("女"); } } } // NewObj.java public class NewObj{ public static void main(String[] args){ Test test = new Test(); test.height = 170; test.age = 20; test.sex = 0; test.printBaseMes(); } }
關於對象中各變量的作用域:
1.局部變量的作用域僅限於定義它的方法內。而成員變量的作用域在整個類內部都是可見的。
2.同時在相同的方法中,不能有同名的局部變量;在不同的方法中,可以有同名的局部變量。
3.成員變量和局部變量同名時,局部變量具有更高的優先級。
構造方法
-
每個類至少會生成一個構造方法
1.構造方法名稱與類名相同,沒有返回值。
2.如定義類時如未定義構造方法,系統自動生成無參構造方法;如定義,則不再自動生成。// Test1.java public class Test1{ double height; int age; public Test1(double h, int a){ height = h; age = a; } void print(){ System.out.println("我的身高:" + height); System.out.println("我的年齡:" + age); } }
// NewObj.java public class NewObj{ public static void main(String[] args){ Test1 t1 = new Test1(170, 22); t1.print(); } }
3.構造方法的重載:可以定義多個構造方法,使用時系統據給定的不同參數自動選擇相應的構造方法。
// Test1.java public class Test1{ double height; int age; int sex; // 性別,0爲男,非0爲女 public Test1(double h, int a){ height = h; age = a; } public Test1(int s){ sex = s; } void print(){ System.out.println("我的身高:" + height); System.out.println("我的年齡:" + age); } void printSex(){ if (sex == 0){ System.out.println("男"); } else{ System.out.println("女"); } } }
// NewObj.java public class NewObj{ public static void main(String[] args){ Test1 t1 = new Test1(170, 22); t1.print(); Test1 t2 = new Test1(0); t2.printSex(); } }
引用與對象實例
當Java新建一個對象時,只是創建了一種引用,類似於c語言中的指針,指向內存中存儲數據的地址。
static
- 靜態成員(或類成員)
// Static.java public class Static{ public static String str = "shiyan"; public String str1 = "test"; public static void main(String[] args){ // 靜態成員,不需要實例化可以直接通過類名訪問 System.out.println(Static.str); // 非靜態成員,必須實例化後纔可訪問 Static str2= new Static(); System.out.println(str2.str1); } }
- 靜態方法
不需要實例化即可調用。
不能使用關鍵字this
,不能訪問非靜態成員和非靜態方法。
final
final 修飾類,則該類不允許被繼承,爲最終類
final 修飾方法,則該方法不允許被覆蓋(重寫)
final 修飾屬性,則該類的屬性不會進行隱式的初始化(類的初始化屬性必須有值)或在構造方法中賦值(但只能選其一)
final 修飾變量,則該變量的值只能賦一次值,即常量
public final static String Test = "test";
封裝
隱藏對象的屬性和實現細節,僅對外公開接口,並控制對象屬性的讀和修改的權限。
- 權限修飾符
訪問修飾符 | 本類 | 同包 | 子類 | 其它 |
---|---|---|---|---|
private | 1 | |||
默認 | 1 | 1 | ||
protected | 1 | 1 | 1 | |
public | 1 | 1 | 1 | 1 |
- getter/setter
對外提供的每個屬性讀寫的公共訪問方法。並在getter/setter中加入判斷語句,否定非法輸入。
// Test1.java
public class Test1{
private double height;
public double getHeight(){
return height;
}
public void setHeight(double newHeight){
height = newHeight;
}
}
// NewObj.java
public class NewObj{
public static void main(String[] args){
Test1 t1 = new Test1();
t1.setHeight(177);
System.out.println(t1.getHeight());
}
}
- this
代表當前對象。
當成員變量與局部變量相同時,局部變量優先級更高。如需訪問成員變量,使用this.屬性
。方法亦同。
繼承
解決代碼複用的問題。
class 子類 extends 父類
子類擁有父類除
private
以外的所有屬性和方法;
子類可以有自己的屬性和方法;
子類可以重寫父類的方法;
Java中的繼承是單繼承,一個類只有一個你類。
補:Java實現多繼承的方法implements接口。
// Animal.java
public class Animal{
public int legNum;
public void bark(){
System.out.println("叫");
}
}
// Dog.java
public class Dog extends Animal{
}
// Test.java
public class Test{
public static void main(String[] args){
Dog dog = new Dog();
dog.legNum = 4;
dog.bark();
}
}
- super
在子類內部使用,代表父類對象。
1.父類屬性:super.屬性
2.父類方法:super.bark()
3.子類構造方法需要調用父類的構造方法時,在子類構造方法體最前面加上:super()
方法重載與重寫
- 方法重載
一個類中可以定義多個同名的方法,但每個方法的參數類型或參數個數都不一樣。
方法中的參數列表必須不同。比如:參數個數不同或者參數類型不同。
重載的方法中允許拋出不同的異常
可以有不同的返回值類型,但是參數列表必須不同
可以有不同的訪問修飾符
public class Test{
void f(int i){
System.out.println(i);
}
void f(double d){
System.out.println(d);
}
void f(String s1, String s2){
System.out.println(s1 + s2);
}
void f(String s, int i){
System.out.println(s + ", " + i);
}
public static void main(String[] args){
Test t = new Test();
t.f(0);
t.f(1.0);
t.f("I", "love u");
t.f("I", 4);
}
}
- 方法重寫
子類繼承父類的方法後,可以方法進行重寫。
// Animal.java
public class Animal{
void bark(){
System.out.println("叫");
}
}
// Dog.java
public class Dog extends Animal{
// 重寫
void bark(){
System.out.println("汪");
}
}
// Test.java
public class Test{
public static void main(String[] args){
Animal ani = new Animal();
Dog dog = new Dog();
ani.bark();
dog.bark();
}
}
多態
又稱動態綁定。
同一消息,發送給不同的對象,產生不同的行爲。
- 向上轉型
子類可以自動向上轉型爲父類。反之,不行。
public class Test{
public static void main(String[] args){
// Dog -> Animal
// 遺忘子類中與父類不同的方法,重寫與父類相同的方法
Animal ad = new Dog();
ad.bark();
}
}
- 多態的實現條件:繼承、重寫、向上轉型
- 多態的實現方式
1.繼承父類進行方法重寫
2.抽象類和抽象方法
3.接口實現
抽象類
抽象類的實現規則:
用 abstract 修飾符定義抽象類
用 abstract 修飾符定義抽象方法,只用聲明,不需要實現
包含抽象方法的類就是抽象類
抽象類中可以包含普通的方法,也可以沒有抽象方法
抽象類的對象不能直接創建,通常是定義引用變量指向子類對象。
使用抽象類:
1.自上而下的設計時,只需知道父類需要實現哪些功能,不需關心子類具體的實現方式;
2.從多個類中抽象出子類模版。
// TelePhone.java
public abstract class TelePhone{
public abstract void call();
public abstract void message();
}
// CellPhone.java
public class CellPhone extends TelePhone{
@Override
public void call(){
System.out.println("打電話");
}
@Override
public void message(){
System.out.println("發短信");
}
public static void main(String[] args){
CellPhone c = new CellPhone();
c.call();
c.message();
}
}
接口
用於描述類所具有的功能,而不提供實現的方式。
修飾符 interface 接口名稱 [extends 其它接口名]{
// 聲明變量
// 抽象方法
}
// 多繼承實現方式
修飾符 interface A extends 接口1,接口2{
}
修飾符 class A implements 接口1, 接口2{
}
// Animal.java
interface Animal{
int y = 7;
public void eat();
public void run();
}
// Dog.java
public class Dog implements Animal{
public void eat(){
System.out.println("Dog eat");
}
public void run(){
System.out.println("Dog run");
}
public static void main(String[] args){
Dog d = new Dog();
System.out.println(d.y);
d.eat();
d.run();
}
}
內部類
將一個類定義到另一個類的內部。與之對應的類爲外部類。作用:
1.更好的封裝;
2.內部類可以訪問外部類的所有變量;
3.有些功能使用內部類可以更好的實現;
4.內部類允許繼承多個非接口類型。
內部類是一個編譯時的概念,一旦編譯成功,就會成爲完全不同的兩類。對於一個名爲 outer 的外部類和其內部定義的名爲 inner 的內部類。編譯完成後出現 outer.class 和 outer$inner.class 兩類。所以內部類的成員變量/方法名可以和外部類的相同。
- 成員內部類
// Animal.java
public class Animal{
private int ID = 0;
// 內部類 Dog
public class Dog{
String name = "dog";
public void bark(){
System.out.println("汪");
}
}
public static void main(String[] args){
Animal ani = new Animal();
Dog dog = ani.new Dog();
dog.bark();
}
}
1.Dog相當於Animal的一個成員變量;
2.Dog的方法可以訪問Animal的所有屬性和方法;
3.成員內部類的實例化:內部類 對象名 = 外部類.new 內部類();
4.如內部類與外部類有相同屬性或方法,內部類默認優先訪問內部類的屬性或方法。如需訪問外部類的屬性或方法,使用this
關鍵字;
5.成員內部類不能含有 static 的變量和方法,因爲成員內部類需要先創建了外部類,才能創建它自己。
- 靜態內部類
嵌入類。
// Animal.java
public class Animal{
private int legNum = 4;
static String ID = "20200001";
static int age = 3;
public static class Dog{
String ID = "20200002";
public void printInfo(){
System.out.println("Dog ID:" + ID);
System.out.println("Animal age:" + age);
System.out.println("Animal ID:" + Animal.ID);
System.out.println("Animal legNum:" + new Animal().legNum);
}
}
public static void main(String[] args){
Dog dog = new Dog();
dog.printInfo();
}
}
1.靜態內部類成員名與外部靜態成員名相同時,靜態內部類優先訪問自身的成員:成員
;
2.外部類的靜態成員名與靜態內部類不同名時,靜態內部類可直接訪問:成員
;
3.靜態內部類訪問外部類的靜態成員:外部類名.靜態成員
;
4.靜態內部類訪問外部類的非靜態成員:new 外部類().成員
。
5.靜態內部類可以直接實例化:靜態內部類 對象 = new 靜態內部類()
.
- 局部內部類
內部類定義在方法和作用域內。
// Animal.java
public class Animal{
// 定義在方法內
public void printInfo(){
final String NAME = "Animal";
class Dog{
String ID = "20200002";
public void print(){
System.out.println("Dog ID:" + ID);
System.out.println("printInfo() NAME:" + NAME);
}
}
Dog dog = new Dog();
dog.print();
}
// 定義在作用域內
public void printInfo2(boolean b){
if (b){
final String NAME = "Animal_";
class Dog{
String ID = "20200002_";
public void print(){
System.out.println("Dog ID:" + ID);
System.out.println("printInfo2() NAME:" + NAME);
}
}
Dog dog = new Dog();
dog.print();
}
}
// test
public static void main(String[] args){
Animal ani = new Animal();
// 方法內
ani.printInfo();
// 作用域內
ani.printInfo2(true);
}
}
如何理解定義在作用域內?
- 匿名內部類
沒有名字的內部類,只能使用一次,通常用來簡化代碼。
使用前提:必須繼承一個父類,或實現一個接口
。
// Outer.java
public class Outer{
public Inner getInner(final String name, String city){
return new Inner(){
private String nameStr = name;
public String getName(){
return nameStr;
}
};
}
public static void main(String[] args){
Outer outer = new Outer();
Inner inner = outer.getInner("Inner", "NewYork");
System.out.println(inner.getName());
}
}
interface Inner{
String getName();
}
1.匿名類不能加訪問修飾符;
2.new 匿名類(),要先定義,否則會報錯;
3.當所匿名類所在方法的形參需要在匿名類內部使用時,必需使用final
;
// 因匿名內部類無名字,默認無參構造函數
// 帶參構造函數的實現
public Inner getInner(final String name, string city){
return new Inner(name, city){
private String nameStr = name;
public String getName(){
return nameStr;
}
};
}