Java程式設計入門筆記(八)
隨遇而安——多型
為什麼使用多型?
不用為每一增加的子類增加對應的麻煩,最重要又可以偷懶了~
什麼是多型?
多型:同一個引用型別,使用不同的例項而執行不同操作
使用父類作為方法形參實現多型
使用父類作為形式引數,可以接受子類的物件作為實參。
進入到方法之後,該物件僅能當做父類使用,無法訪問子類的成員。
public class Master {
public void feed( Pet pet ) {
//使用父類作為方法形參
}
}
// 測試方法
Dog dog = new Dog();
Master master = new Master();
master. feed( dog );
//同一種操作方式,不同的操作物件
父類作為返回值
使用父類作為返回值型別,可以返回任意子類的例項
public class Master {
public Pet chooseRandomPet(Pet[] pets){
… …
}
}
父類到子類的轉換
public class Dog extends Pet {
public void catchingFlyDisc() {
… …
}
}
public class Penguin extends Pet {
public void swimming () {
… …
}
}
public class Master {
public void play(Pet pet){
// pet.catchingFlyDisc();
//報錯,父類引用不能呼叫子類特有方法
Dog dog = (Dog)pet;
dog.catchingFlyDisc();
//可以使用強制型別轉換,將父類轉換成子類型別
}
}
//測試類
Pet pet = new Dog();
Master master = new Master();
master.playWith(pet);
判斷父類例項的類別
instanceof運算子
語法:物件 instanceof 類或介面
public class Master {
public void play(Pet pet){
if (pet instanceof Dog) { //如果傳入的是狗狗
Dog dog = (Dog) pet;
dog.catchFlyingDisc();
}else if (pet instanceof Penguin) { //如果傳入的是企鵝
Penguin pgn = (Penguin) pet;
pgn.swim();
}
}
}
塑型
- 塑型(type-casting)又稱為型別轉換
- 方式
隱式(自動)的型別轉換
顯式(強制)的型別轉換 - 塑型的物件包括
- 基本資料型別
將值從一種形式轉換成另一種形式- 引用變數
將物件暫時當成更一般的物件來對待,並不改變其型別
只能被塑型為- 任何一個父類型別
- 物件所屬的類實現的一個介面
- 被塑型為父類或介面後,再被塑型回其本身所在的類
- 引用變數
隱式(自動)的型別轉換
- 基本資料型別
相容型別之間儲存容量低的自動向儲存容量高的型別轉換 - 引用變數
- 被塑型成更一般的類
Employee emp;
emp = new Manager(); //將Manager型別的物件直接賦給
//Employee類的引用變數,系統會
//自動將Manage物件塑型為Employee類
- 被塑型為物件所屬類實現的介面型別
Car jetta = new Car();
Insurable item = jetta;
顯式(強制)的型別轉換
- 基本資料型別
(int)871.34354; // 結果為 871
(char)65; // 結果為‘A’
(long)453; // 結果為453L
- 引用變數:還原為本來的型別
Employee emp;
Manager man;
emp = new Manager();
man = (Manager)emp; //將emp強制塑型為本來的型別
塑型應用的場合
- 賦值轉換
賦值號右邊的表示式型別或物件轉換為左邊的型別 - 方法呼叫轉換
實參的型別轉換為形參的型別 - 算數表示式轉換
算數混合運算時,不同型別的項轉換為相同的型別再進行運算 - 字串轉換
字串連線運算時,如果一個運算元為字串,一個運算元為數值型,則會自動將數值型轉換為字串
方法的查詢
如果在塑型前和塑型後的類中都提供了相同的方法,如果將此方法傳送給塑型後的物件,那麼系統將會呼叫哪一個類中的方法?
- 例項方法的查詢
- 類方法的查詢
例項方法的查詢
從物件建立時的類開始,沿類層次向上查詢
Manager man = new Manager();
Employee emp1 = new Employee();
Employee emp2 = (Employee)man;
emp1.computePay(); // 呼叫Employee類中的computePay()方法
man.computePay(); // 呼叫Manager類中的computePay()方法
emp2.computePay(); // 呼叫Manager類中的computePay()方法
類方法的查詢
總是在引用變數宣告時所屬的類中進行查詢
Manager man = new Manager();
Employee emp1 = new Employee();
Employee emp2 = (Employee)man;
man.expenseAllowance(); //in Manager
emp1.expenseAllowance(); //in Employee
emp2.expenseAllowance(); //in Employee!!!
繫結
指將一個方法呼叫同一個方法主體連線到一起
- 根據繫結時期的不同,可分為
- 早期繫結
程式執行之前執行繫結 - 晚期繫結
也叫作“動態繫結”或“執行期繫結
基於物件的類別,在程式執行時執行繫結
- 早期繫結
//基類Shape建立了一個通用介面
class Shape {
void draw() {}
void erase() {}
}
//派生類覆蓋了draw方法,為每種特殊的幾何形狀都提供獨一無二的行為
class Circle extends Shape {
void draw()
{ System.out.println("Circle.draw()"); }
void erase()
{ System.out.println("Circle.erase()"); }
}
class Square extends Shape {
void draw()
{ System.out.println("Square.draw()"); }
void erase()
{ System.out.println("Square.erase()"); }
}
class Triangle extends Shape {
void draw()
{ System.out.println("Triangle.draw()"); }
void erase()
{ System.out.println("Triangle.erase()"); }
}
// 對動態繫結進行測試如下
public class BindingTester{
public static void main(String[] args) {
Shape[] s = new Shape[9];
int n;
for(int i = 0; i < s.length; i++) {
n = (int)(Math.random() * 3);
switch(n) {
case 0: s[i] = new Circle(); break;
case 1: s[i] = new Square(); break;
case 2: s[i] = new Triangle();
}
}
for(int i = 0; i < s.length; i++) s[i].draw();
}
}
執行結果
Square.draw()
Triangle.draw()
Circle.draw()
Triangle.draw()
Triangle.draw()
Circle.draw()
Square.draw()
Circle.draw()
Triangle.draw()
說明
編譯時無法知道s陣列元素的具體型別,執行時才能確定型別,所以是動態繫結
在主方法的迴圈體中,每次隨機生成指向一個Circle、Square或者Triangle的引用
所有類都在music包中
Note類中定義了三個音符
Instrument類中宣告並實現了一個play方法
Wind類繼承了Instrument類,過載了play方法
Music類中包含了main方法
class Note {
private int value;
private Note(int val) { value = val; }
public static final Note
MIDDLE_C = new Note(0),
C_SHARP = new Note(1),
B_FLAT = new Note(2);
}
class Instrument {
public void play(Note n) {
System.out.println("Instrument.play()");
}
}
class Wind extends Instrument {
public void play(Note n) {
System.out.println("Wind.play()");
}
}
public class Music {
public static void tune(Instrument i) {
i.play(Note.MIDDLE_C);
}
public static void main(String[] args) {
Wind flute = new Wind();
tune(flute);
}
}
執行結果
Wind.play()
說明
執行中,Instrument類的物件實際是Wind類的,所以呼叫了Wind類中的play方法
內部類
- 在另一個類或方法的定義中定義的類
- 可訪問其外部類中的所有資料成員和方法成員
- 可對邏輯上相互聯絡的類進行分組
- 對於同一個包中的其他類來說,能夠隱藏
- 可非常方便地編寫事件驅動程式
- 宣告方式
- 命名的內部類:可在類的內部多次使用
- 匿名內部類:可在new關鍵字後宣告內部類,並立即建立一個物件
- 假設外層類名為Myclass,則該類的內部類名為
Myclass$c1.class (c1為命名的內部類名)
Myclass$1.class (表示類中宣告的第一個匿名內部類)
public class Parcel1 {
class Contents { //內部類
private int i = 11;
public int value() { return i; }
}
class Destination { //內部類
private String label;
Destination(String whereTo) { label = whereTo; }
String readLabel() { return label; }
}
public void ship(String dest) {
Contents c = new Contents();
Destination d = new Destination(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel1 p = new Parcel1();
p.ship("Tanzania");
}
}
說明
在Parcel1類中聲明瞭兩個內部類Contents、Destination
在ship方法中生成兩個內部類物件,並呼叫了內部類中宣告的一個方法
外部類的方法可以返回內部類的引用變數
public class Parcel2 {
class Contents {
private int i = 11;
public int value() { return i; }
}
class Destination {
private String label;
Destination(String whereTo) { label = whereTo; }
String readLabel() { return label; }
}
public Destination to(String s)
{ return new Destination(s); }
public Contents cont() { return new Contents(); }
public void ship(String dest) {
Contents c = cont();
Destination d = to(dest);
System.out.println(d.readLabel());
}
public static void main(String[] args) {
Parcel2 p = new Parcel2();
p.ship("Tanzania");
Parcel2 q = new Parcel2();
Parcel2.Contents c = q.cont();
Parcel2.Destination d =q.to("Borneo");
}
}
說明
to()方法返回內部類Destination的引用
cont()方法返回內部類Contents的引用
內部類實現介面(介面在下一節)
內部類實現介面
- 可以完全不被看到,而且不能被呼叫
- 可以方便實現“隱藏實現細則”。你所能得到的僅僅是指向基類(base class)或者介面的一個引用
abstract class Contents {
abstract public int value();
}
interface Destination {
String readLabel();
}
public class Parcel3 {
private class PContents extends Contents {
private int i = 11;
public int value() { return i; }
}
protected class PDestination implements Destination {
private String label;
private PDestination(String whereTo) { label = whereTo;}
public String readLabel() { return label; }
}
public Destination dest(String s) { return new PDestination(s); }
public Contents cont() { return new PContents(); }
}
class Test {
public static void main(String[] args) {
Parcel3 p = new Parcel3();
Contents c = p.cont();
Destination d = p.dest("Tanzania");
}
}
說明
內部類PContents實現了抽象了Contents
內部類PDenstination實現了介面Destination
外部類Test中不能宣告對private的內部類的引用
方法中的內部類
在方法內定義一個內部類
- 為實現某個介面,產生並返回一個引用
- 為解決一個複雜問題,需要建立一個類,而又不想它為外界所用
public class Parcel4 {
public Destination dest(String s) {
class PDestination implements Destination {
private String label;
private PDestination(String whereTo) {
label = whereTo;
}
public String readLabel() { return label; }
return new PDestination(s);
}
public static void main(String[] args) {
Parcel4 p = new Parcel4();
Destination d = p.dest("Tanzania");
}
}
public class Parcel5 {
private void internalTracking(boolean b) {
if(b) {
class TrackingSlip {
private String id;
TrackingSlip(String s) { id = s; }
String getSlip() { return id; }
}
TrackingSlip ts = new TrackingSlip("slip");
String s = ts.getSlip();
}
}
public void track() { internalTracking(true); }
public static void main(String[] args) {
Parcel5 p = new Parcel5();
p.track();
}
}
public class Parcel6 {
public Contents cont() {
return new Contents() {
private int i = 11;
public int value() { return i; }
};
}
public static void main(String[] args) {
Parcel6 p = new Parcel6();
Contents c = p.cont();
}
}
匿名的內部類
基類需要一個含引數的構造方法
public class Parcel7 {
public Wrapping wrap(int x) {
return new Wrapping(x) {
public int value() { return super.value() * 47; }
};
}
public static void main(String[] args) {
Parcel7 p = new Parcel7();
Wrapping w = p.wrap(10);
}
}
匿名內部類物件的初始化
public class Parcel8 {
public Destination dest(final String dest) {
return new Destination() {
private String label = dest;
public String readLabel() { return label; }
};
}
public static void main(String[] args) {
Parcel8 p = new Parcel8();
Destination d = p.dest("Tanzania");
}
}
通過例項初始化構造匿名內部類
public class Parcel9 {
public Destination dest(final String dest, final float price) {
return new Destination
相關推薦
Java程式設計入門筆記(八)
隨遇而安——多型
為什麼使用多型?
不用為每一增加的子類增加對應的麻煩,最重要又可以偷懶了~
什麼是多型?
多型:同一個引用型別,使用不同的例項而執行不同操作
使用父類作為方法形參實現多型
使用父類作為
Java程式設計入門筆記(二)
驀然回首——資料型別和運算子
分類
資料型
例如int,short,long,double等等
非資料型
String,char
變數命名規則
變數名首字母
字母,
Java程式設計入門筆記(四)
你若安好——類和物件
萬物皆物件
屬性——物件具有的各種特徵
每個物件的每個屬性都擁有特定值
例如:每個學生的姓名、體重都不一樣
方法——物件執行的操作
物件:用來描述客觀事物的一個實體,由一組屬性
Java程式設計入門筆記(十一)
海納百川——物件陣列和集合
物件陣列
陣列
在Java提供的儲存及隨機訪問物件序列的各種方法中,陣列是效率最高的一種
型別檢查
邊界檢查
優點
陣列知道其元素的型別
編譯時的型別檢查
大小已知
代價
陣列物件的大小是固定的,在生存期內大小不可變
物件
java程式設計規範筆記(一)
1. 命名風格
程式碼中的命名均不能以下劃線或美元符號開始,也不能以下劃線或美元符號結束
程式碼中的命名嚴禁使用拼音與英文混合的方式,更不允許直接使用中文的方式
類名使用UpperCamelCase風格,必須遵從駝峰形式
方法名、引數名
java程式設計規範筆記(二)
(二)常量定義
不允許任何魔法值(即未經定義的常量)直接出現在程式碼中
long或者Long初始賦值時,使用大寫的L,不能是小寫的l,小寫容易跟數字1混淆,造成誤解
不要使用一個常量類維護所有常量,按常量功能進行歸類,分開維護
(三) 程式碼格式
Java程式設計規範筆記(三)
(四) OOP規約
避免通過一個類的物件引用訪問此類的靜態變數或靜態方法,無謂增加編譯器解析成本,直接用類名來訪問即可
所有的覆寫方法,必須加@Override註解
相同引數型別,相同業務含義,才可以使用Java的可變引數,避免使用Object(
ECMAScript 6 入門筆記(八)Proxy,Reflect
Proxy
proxy用於修改某些操作的預設行為,等同於在語言層面作出修改,屬於”超程式設計”。可以理解成架設一層“攔截”,外界對該物件訪問都必須通過這層攔截。
var obj = new Proxy({},{
get: function
JAVA程式設計思想學習筆記(八)介面
介面
抽象類和抽象方法
抽象方法:這種方法不完整,僅有宣告而沒有方法體。所採用的語法如下:
abstract void f();
抽象類:包含抽象方法的類叫做抽象類,如果一個類包含一個或多個抽象方法,該類必須被限定為抽象的。
介面
關鍵字:interface 介面定
Java併發程式設計的藝術筆記(八)——執行緒池
一.執行緒池的主要處理流程
ThreadPoolExecutor執行execute方法分下面4種情況。
1)如果當前執行的執行緒少於corePoolSize,則建立新執行緒來執行任務(注意,執行這一步需要獲取全域性鎖)。
2)如果執行的執行緒等於或多於corePoolSize,則將任
java學習筆記(八):繼承
this關鍵字 log implement java學習 方式 show 使用 類型 多繼承 繼承
子類擁有父類非private的屬性,方法。
子類可以擁有自己的屬性和方法,即子類可以對父類進行擴展。
子類可以用自己的方式實現父類的方法。
Java的繼承
Java框架spring Boot學習筆記(八):Spring相關概念
擴展 靜態 輕量級 想要 spring配置 核心 使用 oot 調用方法 Spring是開源、輕量級、一站式框架。
Spring核心主要兩部分
aop:面向切面編程,擴展功能不是修改源代碼實現
ioc:控制反轉,比如一個類,在類裏面有方法(不是靜態的方法),想要調用類
Elastic Stack 筆記(八)Elasticsearch5.6 Java API
erl java api 編寫 ack apach fail row 擴展庫 都是 博客地址:http://www.moonxy.com
一、前言
Elasticsearch 底層依賴於 Lucene 庫,而 Lucene 庫完全是 Java 編寫的,前面的文章都是發送的
python | 爬蟲筆記 - (八)Scrapy入門教程
RoCE yield ini 配置 自己 數據存儲 2.3 rom 提取數據 一、簡介
Scrapy是一個基於Twisted 的異步處理框架,是針對爬蟲過程中的網站數據爬取、結構性數據提取而編寫的應用框架。 可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。
java學習筆記(八)-- 異常
異常體系圖
Error:描述Java執行時內部錯誤與資源耗盡錯誤(OOM,StackOverflow)應用程式不丟擲此類異常。這種內部錯誤一旦出現,除了告知使用者並使用安全終止之外,再無能為力。
Exception(程式本身錯誤):Java應用程式丟擲異常。
IOExce
Java自學筆記(八)
面向物件——繼承
繼承的思想其實很好理解,但是裡面有些東西需要記憶。
理解,繼承可以將之前的類沿襲下來,保留被繼承類的功能。
使用方法:class 類名稱 extends 父類名稱 {
……
}
例項:
學習筆記(八):使用邏輯迴歸檢測JAVA溢位攻擊以及識別驗證碼
(1)檢測JAVA溢位攻擊
1.資料蒐集:載入ADFA-LD正常樣本資料,定義遍歷目錄下檔案的函式,從攻擊資料集中篩選和JAVA溢位攻擊相關的資料,原理同(四)
2.特徵化:與(四)一致,使用詞集模型
3.訓練樣本
logreg = linear_model.LogisticRegr
java丨事件驅動程式設計學習筆記(二)
一、匿名監聽器 監聽器類是特意為建立一個GUI元件(例如,一個按鈕)而設計的監聽物件。監聽器類不被其他應用程式所共享,因此,正確的做法是將它作為一個內部類定義在框架中。 可以使用匿名內部類簡化內部類監聽器。匿名內部類時沒有名字的內部類。它進一步完成定義內部類和建立一個該類的例項。 內部類Enlarg
java基礎筆記(八)構造方法
給成員變數賦值有倆種方式: setXxx(); 構造方法
構造方法: 給物件的資料進行初始化 格式:
方法名與類名一致
無資料型別,void都沒有
無返回型別
public class ConstructionMethodDemp {