这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战
文章目录
- 需要知道的知识点
- 举例1:Weapon接口 ,理解接口的使用
- 举例2:Bird 类 。接口使用之一:解决多重继承问题
- 举例3:Calculator 接口 。接口使用之二:定义一个规范(协议)
- 举例4:OnInfoFetchCallback 。接口使用之三:用于回调
需要知道的知识点
1、百度百科的定义:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
Java中的接口可以被看作是只包含常量和抽象方法的抽象类 。
2、接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。它和类的区别是用interface
来代替class
关键字,用implements
来代替extends
关键字。
接口的定义格式:
interface 接口名称{
全局常量 ;
抽象方法 ;
}
复制代码
3、在一个接口中,只能定义常量、抽象方法,JDK1.8后可以定义默认的实现方法
4、接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。
5、类只能继承1个类,但可以实现多个接口
class A extends B implements C,D,E{
}
复制代码
6、接口之间继承,接口继承接口可以多继承
interface A extends B,C,D{
}
复制代码
7、java8新增
(1)增加了 default 方法和 static 方法,这两种方法完全可以有方法体
(2)default 方法属于实例,static 方法属于类(接口)
(3)接口中的静态方法不会被继承,接口中的静态变量会被继承
举例1:Weapon接口 ,理解接口的使用
我们创建一个武器接口 Weapon
定义了武器类型有:冷兵器(TYPE_CODE)、热兵器(TYPE_HEAT)、核武器(TYPE_NUCLEAR)
定义了武器的方法有 :攻击(kill)、获取武器名称(getName)、获取武器类型(getType)
接着我们创建冷兵器倚天剑类 Sword类和热兵器 AK47 类 都实现 Weapon 接口。
Weapon
|————–冷兵器:倚天剑
|————–热兵器:AK47
创建Weapon接口
public interface Weapon {
//接口中的属性默认为public static final,所以可省
public static final int TYPE_COLD = 1;
int TYPE_HEAT = 2;
//必须是公共、抽象的,public abstract可以省略
//接口中的方法会被隐式的指定为 public abstract
//而且只能是 public abstract(公共、抽象的),所以可省
public abstract void kill(TextView textView);
String getName();
int getType();
}
复制代码
创建Sword类
public class Sword implements Weapon {
@Override
public void kill(TextView textView) {
textView.append("舞出了一套太极剑法");
}
@Override
public String getName() {
return "倚天剑";
}
@Override
public int getType() {
return Weapon.TYPE_COLD;
}
}
复制代码
创建AK47类
public class AK47 implements Weapon {
@Override
public void kill(TextView textView) {
textView.append("连续射出了100发子弹");
}
@Override
public String getName() {
return "AK47";
}
@Override
public int getType() {
return Weapon.TYPE_HEAT;
}
}
复制代码
xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_transformer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="变形金刚" />
<Button
android:id="@+id/btn_sword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="倚天剑" />
<Button
android:id="@+id/btn_ak47"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="AK47" />
<Button
android:id="@+id/btn_kill"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="进攻" />
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#222222"
android:textSize="20sp" />
</LinearLayout>
复制代码
为了方便使用武器,我们创建一个变形金刚类 Transformer ,只要把创建的武器实例放到它手里(setWeapon()
方法),然后就可以进行攻击了(调用attack()
方法)
创建Transformer类
public class Transformer {
private Weapon w;
public void setWeapon(Weapon w) {
this.w = w;
}
public void attack(TextView textView) {
if (w == null) {
textView.setText("没有武器,用牙咬吗?");
return;
}
String type = "";
switch (w.getType()) {
case Weapon.TYPE_COLD:
type = "冷兵器";
break;
case Weapon.TYPE_HEAT:
type = "热兵器";
break;
}
textView.setText("使用" + type + w.getName());
w.kill(textView);
}
}
复制代码
MainActivity
public class MainActivity extends AppCompatActivity {
Button btnTransformer;
Button btnSword;
Button btnAK47;
Button btnKill;
TextView textView;
Transformer transformer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnTransformer = findViewById(R.id.btn_transformer);
btnSword = findViewById(R.id.btn_sword);
btnAK47 = findViewById(R.id.btn_ak47);
btnKill = findViewById(R.id.btn_kill);
textView = findViewById(R.id.text);
}
public void doClick(View view) {
switch (view.getId()) {
case R.id.btn_transformer:
createTransformer(textView);
break;
case R.id.btn_sword:
createSword();
break;
case R.id.btn_ak47:
createAK47();
break;
case R.id.btn_kill:
kill();
break;
}
}
private void createTransformer(TextView textView) {
transformer = new Transformer();
textView.setText("已经创建变形金刚");
}
public void createSword() {
Sword sword = new Sword();
transformer.setWeapon(sword);
textView.setText("接入倚天剑");
}
public void createAK47() {
AK47 ak47 = new AK47();
transformer.setWeapon(ak47);
textView.setText("接入AK47");
}
public void kill() {
transformer.attack(textView);
}
}
复制代码
运行程序:
举例2:Bird 类 。接口使用之一:解决多重继承问题
Java 语言本身是不支持类的多重继承(多重继承是指一个类从多个类继承而来,即一个类拥有多个超类)的,但一个类却可以实现多个接口。这样,我们可以将一些抽象方法定义在接口中,间接地达到多重继承的目的。
我们现在有接口 MyInterface1有 飞翔(fly)方法、接口 MyInterface2 有行走(walk)方法
人类能走路所以可以实现 MyInterface2 。而鸟类既能走路也能飞翔,所以要实现 MyInterface1 和 MyInterface2 两个接口。这样就解决“多重继承”的问题
MyInterface1.java
public interface MyInterface1 {
void fly();
}
复制代码
MyInterface2.java
public interface MyInterface2 {
void walk();
}
复制代码
Bird.java
public class Bird implements MyInterface1, MyInterface2 {
private static final String TAG = "Bird";
@Override
public void fly() {
Log.i(TAG, "I can fly");
}
@Override
public void walk() {
Log.i(TAG, "I can walk");
}
}
复制代码
举例3:Calculator 接口 。接口使用之二:定义一个规范(协议)
同一个接口可以有多个不同的实现类,但每一个实现类都必须重写接口中所有的抽象方法。即接口不考虑这些实现类各自采用什么方式实现这些功能,但它要求所有的实现类都必须有这些功能。
例如:
首先定义一个计算器的接口:ICalculator.java,所有实现该接口的类,都必须具有计算两个数相加、相减、相乘、相除的功能。
ICalculator
public interface ICalculator {
/**
* 计算器可以计算两个数的和
*/
int add(int a, int b);
/**
* 计算器可以计算两个数的差
*/
int sub(int a, int b);
/**
* 计算器可以计算两个数的积
*/
long mul(int a, int b);
/**
* 计算器可以计算两个数的商
*/
float div(int a, int b);
}
复制代码
创建实现该接口的类 ACalculator.java
public class ACalculator implements ICalculator {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public int sub(int a, int b) {
return a - b;
}
@Override
public long mul(int a, int b) {
return a * b;
}
@Override
public float div(int a, int b) {
return (float) a / (float) b;
}
}
复制代码
测试使用
在其他类中使用 ACalculator 进行两数之和的计算,其他类并不需要了解ACalculator 是通过什么方式计算的,只需要了解 ICalculator 接口中的相关方法定义即可
ICalculator calculator = new ACalculator();
int sum = calculator.add(12, 14);
System.out.println("sum = " + sum);
复制代码
运行结果:
举例4:OnInfoFetchCallback 。接口使用之三:用于回调
我们知道,一般情况下主线程是不执行耗时任务的,如果遇到一些耗时任务(如网络请求,文件读写,数据库读写等等),我们会将其放入子线程中去执行,当执行完毕后,子线程再将执行结果返回给主线程。这个过程就是回调
首先定义一个回调接口 OnInfoFetchCallback.java
public interface OnInfoFetchCallback {
/**
* 获取信息成功
*/
void onSuccess(String info);
/**
* 获取信息失败
*/
void failure();
}
复制代码
再定义一个用于获取信息的任务类,在这个类中我们执行一些耗时操作 InfoService.java
public class InfoService {
private OnInfoFetchCallback callback;
public InfoService(OnInfoFetchCallback callback) {
this.callback = callback;
}
public void getInfo() {
// 模拟一个耗时操作
Thread thread = new Thread(() -> {
try {
Thread.sleep(3000);
// 信息获取成功,传递结果
callback.onSuccess("结果是:" + new Date());
} catch (InterruptedException e) {
// 信息获取失败
callback.failure();
}
});
thread.start();
}
}
复制代码
xml 中放一个按钮来获取信息
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_getInfo"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="doClick"
android:text="获取信息" />
</LinearLayout>
复制代码
MainActivity
在 MainActivity 中调用 InfoService 中的 getInfo() 方法执行耗时操作
public class MainActivity extends AppCompatActivity implements OnInfoFetchCallback {
private static final String TAG = "OnInfoFetchCallback";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void doClick(View view) {
switch (view.getId()) {
case R.id.btn_getInfo:
fetchInfo();
break;
}
}
/**
* 获取信息
*/
public void fetchInfo() {
InfoService service = new InfoService(this);
service.getInfo();
}
@Override
public void onSuccess(String info) {
Log.i(TAG, info);
}
@Override
public void failure() {
Log.i(TAG, "获取信息失败");
}
}
复制代码
由于 MainActivity 已经实现了 OnInfoFetchCallback
接口,所以在实例化 InfoService 对象时,直接将 this
传入即可。当任务执行结束后,调用 MainActivity 中的 onSuccess(String info)
或 failure()
方法将结果返回
运行结果:
MainActivity 也可以不用实现 OnInfoFetchCallback 接口,此时可以采用匿名内部类的写法:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "OnInfoFetchCallback";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void doClick(View view) {
switch (view.getId()) {
case R.id.btn_getInfo:
fetchInfo();
break;
}
}
/**
* 获取信息
*/
public void fetchInfo() {
InfoService service = new InfoService(new OnInfoFetchCallback() {
@Override
public void onSuccess(String info) {
Log.i(TAG, info);
}
@Override
public void failure() {
Log.i(TAG, "获取信息失败");
}
});
service.getInfo();
}
}
复制代码