多態
什么是多態?
同一個對象在不同時刻表現出來的不同形態(多種形態)例:Cat extends Animal
第一種形態:Cat c1 = new Cat(); //c1是只貓
第二種形態:Animal c2 = new Cat(); //c2是個動物
(多種形態)舉例:數字:2
十進制:2
二進制:00000010
多態的前提 ?
1 有繼承/實現關系2 有方法的重寫
3 父類的引用指向子類的對象
多態的使用?
//多態的代碼體現格式
父類型 對象 = new 子類();//大類型包含小類型 int a = 10; long b = a;
多態代碼的書寫:1. 創建對象//父類型 父引用 = new 子類()Father f = new Son();2. 作為參數public void method( Father f ){f.方法()}3. 作為返回值public Animal getInstance(){//返回:子類對象return new Cat();}
多態在程序中解決什么問題?
1.提高代碼的復用性2.提高代碼的擴展性
public interface Player{public abstract void play();public abstract void stop();
}
public MP3 implements Player{public void play(){System.out.println("mp3播放");}public void stop(){System.out.println("mp3停止");}
}
public MP4 implements Player{public void play(){System.out.println("mp4播放");}public void stop(){System.out.println("mp4停止");}
}
public static void main(String[] args){MP3 mp3 = new MP3();method(mp3);
MP4 mp4 = new MP4();method(mp4);
}
//多態的體現:Player p = new MP3/MP4();
public static void method(Player p){//Player p = mp3
p.play();
p.stop();
}
}//集合:ArrayList類 implements List接口
List list = new ArrayList();
需要改的時候(體現擴展性)List list = new LinkedList();
多態在使用時的注意細節?
1. 多態中:父類和子類擁有一模一樣的成員變量時:
編譯時:以父類型中的成員變量為主運行時:使用父類中的成員變量
2. 多態中:父類和子類擁有一模一樣的成員方法時:
編譯時:以父類中的成員方法為主(檢查父類中有沒有這個成員方法,沒有:報錯)運行時:以子類中的成員方法為主(調用子類對象中重寫后的成員方法)
public class Father {int num = 100;public void show() {System.out.println("父類的show方法");}
}
public class Son extends Father {//成員變量int num = 10;//成員方法public void show() {System.out.println("子類的show方法");}public void show2(){System.out.println("子類特有的方法");}}
public class Test {public static void main(String[] args) {// 父類的引用指向子類的對象Father f = new Son();// 多態對象調用成員變量:調用的是父類的成員變量System.out.println(f.num);// 多態對新對象調用成員方法f.show();// 多態對象不能調用子類特有的方法// f.show2();//向下轉型Son s = (Son)f;//子類 對象 = (子類) 父引用;s.show2();}
}
運行結果:
100
子類的show方法
子類特有的方法
多態的優缺點
多態的好處:提高了程序的擴展性,靈活性
多態形式體現(使用方向):1. 定義方法的時候,使用父類型作為參數,該方法就可以接收這父類的任意子類對象
2 .定義方法的時候, 使用父類作為方法的返回值類型 , 該方法可以返回此父類任意子類對象
3. 定義變量時 , 用父類類型變量接收子類類型對象
多態的弊端:不能使用子類的特有功能
多態轉型
向上轉型(自動類型提升)
例:int a =10; long num = a;//多態: 父類型 父引用 = new 子類(); //子類型變為:父類型 (弊端:父引用不能使用子類特有成員)
向下轉型(強制類型轉換) //解決的問題: 父引用不能使用子類中特有成員
例:long a =100L; int b = (int) a;//多態的向下轉型: 子類 對象 = (子類) 父引用;
注意細節:
向下轉型時容易發生:
java.lang.ClassCastException(類型轉換異常)
解決方案:instanceof
if( 父引用對象 instanceof 子類型 ){
子類型 對象 = (子類型)父引用對象;
對象.特有成員
}
public abstract class Animal {private String breed;private String color;public Animal() {}public Animal(String breed, String color) {this.breed = breed;this.color = color;}public String getBreed() {return breed;}public void setBreed(String breed) {this.breed = breed;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public abstract void eat();
}
-------------------------------------------------------------
public class Cat extends Animal {public Cat() {}public Cat(String breed, String color) {super(breed, color);}@Overridepublic void eat() {System.out.println("貓吃魚...");}public void catchMouse() {System.out.println("抓老鼠...");}
}
------------------------------------------------------------
public class Dog extends Animal {public Dog() {}public Dog(String breed, String color) {super(breed, color);}@Overridepublic void eat() {System.out.println("狗吃骨頭!");}public void lookDoor(){System.out.println("狗看門...");}
}
----------------------------------------------------------------
public class Pig extends Animal {public Pig() {}public Pig(String breed, String color) {super(breed, color);}@Overridepublic void eat() {System.out.println("豬拱白菜...");}public void sleep() {System.out.println("一直再睡...");}
}
---------------------------------------------------------------
public class Test {public static void main(String[] args) {useAnimal(new Cat());//匿名對象作為參數傳遞到方法中System.out.println("---------");useAnimal(new Dog());System.out.println("---------");useAnimal(new Pig());}//使用多態:參數為父類型//向下轉型public static void useAnimal(Animal animal){animal.eat();if(animal instanceof Cat){Cat cat = (Cat) animal;cat.catchMouse();}else if(animal instanceof Dog){Dog dog = (Dog)animal;dog.lookDoor();} else if (animal instanceof Pig) {Pig pig = (Pig) animal;pig.sleep();}}// // 定義一個使用貓類的方法
// public static void useAnimal(Cat c) {// Cat c = new Cat();
// c.eat();
// c.catchMouse();
// }
//
// // 定義一個使用狗類的方法
// public static void useAnimal(Dog d) {// Dog d = new Dog();
// d.eat();
// d.lookDoor();
// }
//
// // 定義一個使用豬類的方法
// public static void useAnimal(Pig p) {// Pig p = new Pig();
// p.eat();
// p.sleep();
// }}
運行結果:
貓吃魚...
抓老鼠...
---------
狗吃骨頭!
狗看門...
---------
豬拱白菜...
一直再睡...
多態的應用之處有哪些 ?
第一 : 以多態形式創建一個類的對象第二 : 方法的參數是一個類或者是一個接口 , 那么我們可以傳入子類對象
第三 : 方法的返回值類型是一個類或者接口 , 那么我們可以返回子類對象
內部類
什么是內部類?
在一個類中,定義了另外一個類(內部類[成員內部類])內部類的使用方法?
public class HelloWorld{
//成員變量
//成員方法
//在一個類中,定義了另外一個類(內部類[成員內部類])
class Hello{
}
}
問題:如何訪問某個類中的成員變量or成員方法?
答案:創建類的對象,通過"對象名.成員"的方式訪問
成員內部類
public class Person {// 心臟class Heart {// 變量-頻率private int rate;//60~75// 跳動方法public void beats() {System.out.println("咚咚咚~~");}}
}
------------------------------------------------------------
public class Test {public static void main(String[] args) {//創建Person對象Person p = new Person();//創建成員內部類對象Person.Heart heart = p.new Heart();
//外部類名.內部類名 變量 = 外部類對象.new 內部類構造方法(參數);heart.beats();}
}
運行結果:咚咚咚~~
局部變量:直接訪問,
內部類成員變量:this 訪問
外部類成員變量:外部類名.this 訪問
public class Person {private String name = "張三";int num = 30;//外部類成員變量class Heart {private int rate;//60~75int num = 20;//內部類成員變量public void beats() {int num = 10;//內部類方法中的局部變量System.out.println(num);//10System.out.println(this.num);//20System.out.println(Person.this.num);//30}}
}
--------------------------------------------------------------
public class Test {public static void main(String[] args) {Person.Heart heart = new Person().new Heart();heart.beats();}
}
--------------------------------------------------------------
匿名內部類:
解決程序中什么問題?
簡化程序中代碼的書寫怎么使用?
//語法格式:new 類名/接口(){//重寫方法}//接口
public interface Flyable {void fly();
}
---------------------------------------------------------------
public class Test2 {public static void main(String[] args) {//調1次new Flyable(){@Overridepublic void fly() {System.out.println("我在學習");}}.fly();//想要調用fly方法:2次Flyable f = new Flyable() {@Overridepublic void fly() {System.out.println("我在玩代碼");}};f.fly();f.fly();}
}
------------------------------------------------------
運行結果:
我在學習
我在玩代碼
我在玩代碼
工具類:為解決某些特定問題,特意編寫的公共類(都可以使用)
1.JDK(java開發工具包) = JRE + 核心類庫核心類庫: jdk提供一些現成的功能,這些功能封裝在不同的類中
2.JDK就提供了一些工具類:Math、Arrays
2.1,Arrays工具類:針對數組,提供了一系列現成的功能(例:排序)
import java.util.Arrays; //導入工具類所在包
import java.util.Comparator;public class ArraysTest {public static void main(String[] args) {//數組Integer[] array = {3, 1, 5, 2, 8, 4};//Integer就是int類型System.out.println("排序前:" + Arrays.toString(array));//對數組進行排序//使用JDK提供的現成工具類:Arrays,實現排序Arrays.sort(array);//默認排序規則: 升序(從小到大)System.out.println("排序后:" + Arrays.toString(array));//程序需求:數組元素必須是從大到小(降序)Arrays.sort(array, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1;}});System.out.println("排序后:" + Arrays.toString(array));}
}
運行結果:
排序前:[3, 1, 5, 2, 8, 4]
排序后:[1, 2, 3, 4, 5, 8]
排序后:[8, 5, 4, 3, 2, 1]
常用API(1)
在Java繼承體系中,有一個頂層父類:Object(鼻祖類)
在java語言中,程序員自定義的類或者jdk中存在的類,直接或間接都要繼承Object繼承了Object類后,就可以使用Object提供的相關方法:
1.boolean equals(Object obj)
-boolean: 方法的返回值類型-Object: 方法傳遞參數的類型
-作用:比較兩個對象是否相同(比較兩個對象的地址值是否相同)
import java.util.Objects;
public class Phone {private String brand;private int price;public Phone() {}@Overridepublic boolean equals(Object o) {//兩個對象地址值相同說明是同一個對象if (this == o) return true;//當要比較的對象是null時,就不需要比較,直接返回:false//當比較兩個對象類型不一樣,不需要比較,直接返回:falseif (o == null || getClass() != o.getClass()) return false;//向下轉型Phone phone = (Phone) o;//基本數據類型比較 使用Objects工具類中的equals方法,比較兩個字符串是否相同// return price == phone.price && Objects.equals(brand, phone.brand);return price == phone.price && this.brand.equals(phone.brand);}@Overridepublic int hashCode() {return Objects.hash(brand, price);}public Phone(String brand, int price) {this.brand = brand;this.price = price;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}
}
--------------------------------------------------------------------
public class Test {//演示:equals方法public static void main(String[] args) {Phone p1 = new Phone("小米",1999);Phone p2 = new Phone("小米",1999);System.out.println(p1);System.out.println(p2);System.out.println("-----------------------------------------");System.out.println(p1==p2);//==比較的是變量中的數據值,比較的是對象中存儲的地址值;p1,p2是對象System.out.println(p1.equals(p2));//Ojbect類中的equals方法,比較的是對象中存儲的地址值
//當希望比較Phone中存儲的數據值時,在Phone中重寫equals方法,不重寫,比較的是地址值}
}
--------------------------------------------------
運行結果:
com.Demo.object.equals.Phone@168b1cc
com.Demo.object.equals.Phone@168b1cc
-----------------------------------------
false
false
2.String toString()
- 作用: 把對象轉換為字符串public class Student {private String name;private int age;public Student() {}@Overridepublic String toString() {return "Student{name=" + name + ", age=" + age + '}';}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
--------------------------------------------------------------
public class Test {//演示:toString方法public static void main(String[] args) {//創建學生對象Student stu = new Student("熊大",23);//把對象轉換為字符串String str = stu.toString();System.out.println(str);System.out.println(stu);}
}
--------------------------------------------------------------
運行結果:
Student{name=熊大, age=23}
比較兩個字符串是否相同 :
1: String類中的equals方法boolean result = 字符串1.equals(字符串2);
2:Objects工具類中的equals方法
boolean result = Objects.equals(字符串1 , 字符串2);
區別:Objects工具類中的equals方法 可以避免NullPointerException異常的發生
import java.util.Objects;public class ObjectsTest {public static void main(String[] args) {String str1 = null;String str2 = "itext";//使用Objects工具類中的API方法:比較兩個字符串是否相同boolean result2 = Objects.equals(str1,str2);System.out.println(result2);//Objects工具類中的equals方法 可以避免NullPointerException異常的發生//使用String類中的API方法:比較兩個字符串是否相同boolean result1 = str1.equals(str2);System.out.println(result1);}
}
--------------------------------------------
運行結果:
報錯
false
日期類型的數據:
public class Emp{ //姓名 private String name;//String表示字符串 //年齡 private int age;//int表示整數 //生日 private Date birthday;
//Date表示日期
}
Date類:
歸屬包:java.util
作用:表示日期時間(精確到毫秒)使用: 構造方法(創建對象)
public Date()
public Date(long time)
import java.util.Date;public class DateTest {//演示:Date對象的使用public static void main(String[] args) {
method1();}public static void method1(){//創建Date對象,輸出實時時間Date date1 = new Date();System.out.println(date1);Date date2 = new Date(0);//傳參時輸出:Date對象 = 1970/1/1 0:0:0 + time毫秒值System.out.println(date2);//成員方法:獲取毫秒值long time = date1.getTime();//返回毫秒值 = 當前Date代表的時間 - 1970/1/1 0:0:0System.out.println(time);}
}
---------------------------------------------------------------------
運行結果:
Wed Jul 16 23:02:33 CST 2025
Thu Jan 01 08:00:00 CST 1970
1752678153025
常用方法DateFormat類
DateFormat類是什么?
DateFormat類是java語言提供的日期格式化類DateFormat類解決什么問題?
對日期進行格式化操作:Date類型 -> String類型 => String format(Date)對日期進行解析操作:String類型 -> Date類型 => Date parse(String )
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class DateFormatTest {//演示:日期格式化、日期解析public static void main(String[] args) throws ParseException {
method1();
String str="2025-07-16 14:07:33";method2(str);//Alt+回車,選第一個解決問題}//把日期轉換為字符串public static void method1(){//日期對象Date date = new Date();System.out.println(date);//創建日期格式化對象SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//日期轉換為字符串(按照日期模板,把日期對象變成相應格式的字符串String strDate = sdf.format(date);System.out.println(strDate);}//把字符串解析為日期public static void method2(String s) throws ParseException {////創建日期格式化對象SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//String類型->Data類型Date date = sdf.parse(s);//Alt+回車System.out.println(date);}
}
-------------------------------------------------------------
運行結果:
Wed Jul 16 23:04:57 CST 2025
2025-07-16 23:04:57
Wed Jul 16 14:07:33 CST 2025
DateFormat類怎么使用?
java.text.DateFormat DataeFormat是一個抽象類,無法實例化。使用子類:SimpleDateFormatDateFormat df = new SimpleDateFormat(“日期模板”); //日期模板:就是使用一些特定的字符,來表示某個日期。
例:yyyy表示全年 MM表示月 dd表示日
DateFormat df = new SimpleDateFormat(“yyyy/MM/dd”);
DateFormat df = new SimpleDateFormat(“yyyy年MM月dd日 HH:mm:ss”);
String format(Date date) //將Date類型的數據,按照日期模板,轉換為字符串
Date parse(String s) //將日期格式的字符串數據,按照日期模板,轉換為Date對象
Calendar類:日歷類(存儲的有日期、時間、日歷信息)
代替java.util.Date類中的過期方法Calendar類的使用: 構造方法、 常用方法
Calendar類是一個抽象類,無法創建對象。
子類:GregorianCalendar
在Calendar類中,提供了一個靜態方法,該靜態方法可以實現:Calendar對象的實例化(底層還是使用GregorianCalendar子類)
獲取Calendar類對象Calendar c = Calendar.getInstance();
Calendar對象中存儲的內容:
獲取Calendar對象中存儲的數據:
//API方法: public int get(int 字段名) //字段名:YEAR MONTH DAY_OF_MONTH在Calendar類中有一些靜態常量: YEAR MONTH DAY_OF_MONTHCalenar.YEAR Calendar.MONTH
//獲取日歷對象中的年
Calendar c = Calendar.getInstance();
int year = c.get( Calenar.YEAR )
import java.util.Calendar;public class CalendarTest {//演示:Calendar日歷類的使用public static void main(String[] args) {//創建Calendar類對象Calendar c = Calendar.getInstance();System.out.println(c);//獲取日歷對象中的:年,月,日int year = c.get( Calendar.YEAR );int month = c.get( Calendar.MONTH );//月分范圍0~11int day = c.get( Calendar.DATE );System.out.println(year+"年"+(month+1)+"月"+day+"日");}
}
給日歷對象設置具體的:年月日時分秒…
//獲取日歷對象中的年Calendar c = Calendar.getInstance(); //日歷對象是基于當前系統日期時間獲取的//修改日歷對象中的信息
public void set(int 字段 , int 數值)
c.set( Calendar.YEAR , 2000 );
//修改日歷對象中的年月日
c.set( 2000, 9, 31 );
import java.util.Calendar;public class CalendarTest2 {public static void main(String[] args) {//給日歷對象設置具體的:年月日時分秒//獲取日歷對象中的年Calendar c = Calendar.getInstance(); //日歷對象是基于當前系統日期時間獲取的//修改日歷對象中的年月日c.set( 2000, 9, 31 );int year = c.get( Calendar.YEAR );int month = c.get( Calendar.MONTH );//月分范圍0~11int day = c.get( Calendar.DATE );System.out.println(year+"年"+month+"月"+day+"日");}
}
給日歷對象中的信息,增加或減少
public void add(int 字段 , int 數值) //數值是負數是減少 , 數據是正數表示增加
import java.util.Calendar;
public class DataFormate3 {public static void main(String[] args) {//創建Calendar類對象Calendar c = Calendar.getInstance();System.out.println(c);//增加一年c.add(Calendar.YEAR,1);System.out.println(c);//減少一年c.add(Calendar.YEAR,-1);System.out.println(c);}
}