一、抽象類(abstract class)
1. 定義:如果一個(gè)類沒有包含足夠多的信息來描述一個(gè)具體的對(duì)象,這樣的類就是抽象類.
- 抽象類不能實(shí)例化,但是也能像普通類一樣在{}中定義成員變量、成員方構(gòu)造方法等。
- 抽象方法:只聲明,不實(shí)現(xiàn)。具體的實(shí)現(xiàn)由繼承它的子類來實(shí)現(xiàn),也就是說,被abstract修飾的方法,方法名后直接跟一個(gè)分號(hào),如:
abstract public void show();
- 一個(gè)類中含有抽象方法(被abstract修飾),那么這個(gè)類必須被聲明為抽象類(被abstract修飾)。
- 構(gòu)造方法、類方法(用static修飾的)不能聲明為抽象方法。
2. 繼承抽象類:使用extends來繼承一個(gè)抽象類
- 如果繼承于一個(gè)抽象類,就必須實(shí)現(xiàn)抽象類里面的抽象方法。
- 如果不實(shí)現(xiàn)抽象方法,也可以把這個(gè)類定義為抽象類。
- 只有抽象類的非抽象子類可以創(chuàng)建對(duì)象
abstract class BaseAndroidStudy {
//定義一個(gè)代碼塊
{
System.out.println("鍛煉身體!");
}
//定義一個(gè)屬性 用于保存數(shù)據(jù)
public String javaBook;
public Dream dream;
//提供構(gòu)造方法
public BaseAndroidStudy(String javaBook,String dream){
this.javaBook = javaBook;
this.dream = new Dream();
this.dream.dreamName = dream;
}
//定義一個(gè)靜態(tài)的常量
public static final String CBOOK = "C Primier";
//定義一個(gè)抽象方法 不需要實(shí)現(xiàn) 子類來實(shí)現(xiàn)
abstract public void studyCLanguage();
//定義一個(gè)普通方法 已經(jīng)確定了這個(gè)方法的具體實(shí)現(xiàn)
public void studyJavaLanguage() {
System.out.println("參加Java培訓(xùn)班");
}
//定義一個(gè)類 內(nèi)部類 用于管理每個(gè)人的理想 夢(mèng)想
class Dream{
private String dreamName;
public void show(){
System.out.println("我的夢(mèng)想是:"+dreamName);
}
}
}
抽象類的使用:
class Student extends BaseAndroidStudy{
String name;
@Override
public void studyCLanguage() {
System.out.println("看書,看視頻");
}
public Student(String name,String bookName,String dream){
super(bookName,dream);
this.name = name;
}
}
public class MyClass {
public static void main(String[] agrs) {
//1.顯示地創(chuàng)建一個(gè)類繼承于抽象類 創(chuàng)建這個(gè)類的一個(gè)對(duì)象
Student xw = new Student("小王","java編程思想","成為高級(jí)工程師");
//2.使用匿名類 只使用一次
BaseAndroidStudy zs = new BaseAndroidStudy("java編程思想","成為高級(jí)工程師") {
@Override
public void studyCLanguage() {
System.out.println(".......");
}
};
}
}
二、接口(interface)
1. 定義:接口在java中是一個(gè)抽象類型,是抽象方法的集合。一個(gè)類通過繼承接口的方式,從而繼承接口的抽象方法。
- 從定義是上看,接口是個(gè)集合,并不是類。類描述了屬性和方法,而接口只包含未實(shí)現(xiàn)的方法。接口和抽象類一樣不能被實(shí)例化,因?yàn)椴皇穷?。但是接口可以被?shí)現(xiàn)(impments關(guān)鍵字)。實(shí)現(xiàn)某個(gè)接口的類必須在類中實(shí)現(xiàn)該接口的全部方法。雖然接口內(nèi)的方法都是抽象的(和抽象方法很像,沒有實(shí)現(xiàn)),但是不需要abstract關(guān)鍵字。
- 接口里面默認(rèn)的都是static final 常量, 默認(rèn)情況下不需要自己寫public static final,不能定義變量
- 接口里面不能定義代碼塊
- 接口里面不能定義構(gòu)造方法
- 接口里面不能添加普通/對(duì)象/實(shí)例方法,必須是抽象的(不能實(shí)現(xiàn)), 默認(rèn)就是public abstract
interface TestInterface2 extends TestInterface{
int I = 100;
int COUNT = 100;
void test();
class Inner{
int name;
public void show(){
System.out.println("內(nèi)部類");
}
}
}
- 如果需要定義已經(jīng)有實(shí)現(xiàn)的方法,使用default
- 接口里面可以定義內(nèi)部類 ,內(nèi)部類默認(rèn)public static
- 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口 , 一個(gè)接口可以繼承多個(gè)接口
class GYLClass implements TestInterface2,TestInterface
2.繼承接口:一個(gè)接口能繼承另一個(gè)接口,和類之間的繼承方式比較相似。接口的繼承使用extends關(guān)鍵字,子接口繼承父接口的方法。
class GYLClass implements TestInterface2,TestInterface{
@Override
public void test() {
TestInterface.Inner inner = new TestInterface.Inner();
inner.show();
}
@Override
public void test2() {
}
@Override
public void test3() {
}
}
//接口的使用
class Test{
public static void main(String[] args){
GYLClass gyl = new GYLClass();
TestInterface2 t = new GYLClass();
}
}
三、接口與抽象類的區(qū)別
-
接口不能用于實(shí)例化對(duì)象。
-
接口沒有構(gòu)造方法。
-
接口中所有的方法必須是抽象方法。
-
接口不能包含成員變量,除了 static 和 final 變量。
-
接口不是被類繼承了,而是要被類實(shí)現(xiàn)。
-
接口支持多繼承。
四、項(xiàng)目實(shí)戰(zhàn)(實(shí)現(xiàn)對(duì)按鈕的監(jiān)聽)

功能圖
1. 創(chuàng)建Activity模板(抽象類)
/**
* 管理界面的抽象類 定義了一個(gè)界面創(chuàng)建到結(jié)束的模板
*/
public abstract class Activity{
//保存這個(gè)界面的所有子視圖
public ArrayList<View> childs = new ArrayList<View>();
//抽象類不用實(shí)現(xiàn) 由子類實(shí)現(xiàn)
//界面創(chuàng)建
public abstract void OnCreate();
//界面銷毀
public abstract void OnDestroy();
}
2. 創(chuàng)建View管理所有視圖的顯示和事件監(jiān)聽
/**
* 管理一個(gè)視圖顯示和事件監(jiān)聽
* 什么情況下需要將一個(gè)父類做成一個(gè)抽象類
* 1.不能直接創(chuàng)建這個(gè)類的對(duì)象
* 2.這個(gè)類里面的某些方法 還不確定怎么實(shí)現(xiàn)
*
*/
public class View {
//所有視圖都擁有的屬性
String backgroundColor;
String borderColor;
//記錄誰想監(jiān)聽這個(gè)事件
//暫時(shí)不確定是誰要監(jiān)聽
//但是要監(jiān)聽的人實(shí)現(xiàn)了這個(gè)接口 內(nèi)部接口
OnClickListener listener;
//所有的視圖都要監(jiān)聽事件
//定義內(nèi)部接口
public interface OnClickListener{
//定義一套方法 約束外部使用這些方法來監(jiān)聽事件
void onClick(View v);
}
}
3. 創(chuàng)建主界面MainActivity
/**
* 管理主界面(程序運(yùn)行起來第一個(gè)界面)
*/
public class MainActivity extends Activity implements View.OnClickListener{
@Override
public void OnCreate() {
//主界面如何布局
}
@Override
public void OnDestroy() {
//銷毀之前需要做點(diǎn)什么事情
System.out.println("......");
}
4. 創(chuàng)建按鈕對(duì)象
/**
* 創(chuàng)建一個(gè)按鈕類
*/
public class Button extends View{
String title;
String titleColor;
public Button(String title,String titleColor){
this.title = title;
this.titleColor = titleColor;
}
}
5. 創(chuàng)建一張圖片
/**
* 顯示一張視圖
*/
public class ImageView extends View{
String picture;
public ImageView(String picture){
this.picture = picture;
}
}
6. 在主界面添加按鈕和圖片
//主界面如何布局
//添加一個(gè)按鈕
button = new Button("分享","紅色");
//添加一張圖片
imageView = new ImageView("星空 ");
7. 實(shí)現(xiàn)控件添加到界?上的過程 抽象類Activity中 添加addChild方法
//將子控件添加到當(dāng)前界面上
//接收的時(shí)候是用父類接收子類
//當(dāng)要訪問子類內(nèi)容的時(shí)候 就要強(qiáng)制轉(zhuǎn)換為對(duì)應(yīng)的類型
public void addChild(View v){
if (v instanceof Button){
Button btn = (Button)v; //強(qiáng)制轉(zhuǎn)換
System.out.println(btn.title+"按鈕顯示到界面上了");
}
if (v instanceof ImageView){
ImageView iv = (ImageView)v;
System.out.println(iv.picture+"圖片顯示到界面上了");
}
//保存子類控件
childs.add(v);
}
8. 將創(chuàng)建好的控件添加到界面上
//將創(chuàng)建的控件添加到當(dāng)前界面
addChild(button);
addChild(imageView);
9. 事件監(jiān)聽 MainActivity實(shí)現(xiàn)接口 == MainActivity需要監(jiān)聽事件
//所有的視圖都要監(jiān)聽事件
//定義內(nèi)部接口
public interface OnClickListener{
//定義一套方法 約束外部使用這些方法來監(jiān)聽事件
void onClick(View v);
}
10. 在MainActivity實(shí)現(xiàn)接?里?的?法
//當(dāng)事件觸發(fā) 就會(huì)調(diào)用OnClick方法
@Override
public void onClick(View v) {
System.out.println("按鈕被點(diǎn)擊了");
}
}
11. 告訴按鈕 是誰要監(jiān)聽他的點(diǎn)擊事件
//如果一個(gè)控件需要監(jiān)聽事件就必須實(shí)現(xiàn)監(jiān)聽事件的接口
//告訴按鈕誰在監(jiān)聽這個(gè)事件
button.listener = this; //表示當(dāng)前類的一個(gè)對(duì)象
12. 使?匿名類給圖片添加事件監(jiān)聽器
//2.
//給ImageView添加一個(gè)事件
imageView.listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
System.out.println("圖片被點(diǎn)擊了");
}
};
13. View中事件接收觸摸事件的方法 用于獲取按鈕被點(diǎn)擊了
//用于控件接收觸摸事件
public void getTouchEvent(){
//調(diào)用監(jiān)聽者里面的OnClick方法
listener.onClick(this);
}
14. MainActivity中添加?法 模擬手觸摸屏幕 將觸摸的事件傳遞給按鈕或者圖片
//模擬觸摸
public void touch(){
//將屏幕觸摸的事件傳遞給按鈕
button.getTouchEvent();
imageView.getTouchEvent();
}
15. 外部使用
public class MyClass {
public static void main(String[] args){
//啟動(dòng)程序 創(chuàng)建界面
MainActivity main = new MainActivity();
//模擬觸摸
main.touch();
}
}
運(yùn)行結(jié)果:
運(yùn)行結(jié)果
計(jì)算代碼運(yùn)行時(shí)間:
public class MyClass {
public static void main(String[]args){
MyCode test = new MyCode();
test.calculate();
}
}
/**
* 模板設(shè)計(jì)模式:
*希望能創(chuàng)建一個(gè)模板
* 使用這個(gè) 模板可以方便地測出代碼塊的執(zhí)行效率
*
*/
abstract class TimeTemplate{
//通過實(shí)現(xiàn)這個(gè)方法 獲得具體測量的代碼
public abstract void code();
//提供方法 實(shí)現(xiàn)測量
public void calculate(){
long start = System.currentTimeMillis();
//測量的代碼
code();
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
class MyCode extends TimeTemplate{
@Override
public void code() {
//寫自己的測試代碼
int total = 0;
for (int i = 0;i < 100000;i++){
total += i;
}
}
}