JavaSE基础——面向对象3:接口与内部类
六、接口
1. 什么是接口?
在JAVA
编程语言中,接口是一个抽象类型,是抽象方法的集合。
接口通常以interface
来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。类的继承只能单继承,但可以通过接口实现(伪)多继承。
- 接口代表一种能力,实现接口,则表示具备了某种功能
- 接口代表一种规范,在实现接口的时候必须遵循相应的规范,比如说重新实现方法的时候参数的要求、返回值的要求等等
接口中定义了一些抽象方法,如果类要实现该接口,则必须给出这些抽象方法的具体实现。因此说接口时一种能力。
2. 接口的特点
- 使用
interface关键字
声明接口 - 接口中可以定义变量,但接口中的变量会隐式地指定为
public static final型变量
- 接口主要是一系列抽象方法的集合,接口中的方法会被隐式地指定为
public abstract 类型
- 接口中都是抽象方法,只有方法名,没有方法体。只能由实现接口的类来重写接口中抽象方法的具体实现
- 接口没有构造方法,不能实例化。
- 接口可以继承接口,而且还可以多继承。
- 类使用
implements关键字
实现接口。在类声明中Implements关键字
放在class声明后面。
3. 接口的实现
3.1 接口实现示例
package com.oop_extends.www;
//声明一个接口,接口名称为Sing
interface Sing {
int vol = 10;//接口中定义的变量会隐式地指定为 public static final变量,一般不会再接口中声明变量
//public static final int vol = 10;
boolean isSing = true;
//接口主要是一系列抽象方法的集合,接口中的方法会被隐式地指定为 public abstract 类型
//因为方法都是抽象方法,因此接口里的方法也都是只有方法名,没有方法体,需要实现接口的类来提供方法的具体细节实现
void singSong(People people);
}
abstract class People { //声明一个抽象类,名称为People
abstract void speak();//声明一个抽象方法,speak
}
class Boy extends People { //继承抽象类要重写父类中的抽象方法speak
@Override
void speak() {
System.out.println("男孩说话");
}
}
class Singer extends People implements Sing {//创建一个子类Singer,继承于父类People,实现接口Sing
//当类要实现接口的时候,除非该类是抽象类,否则该类要重写实现接口里的所有抽象方法
//重写sing接口中的singSong方法,
@Override
public void singSong(People people) {
//在实现接口的抽象方法singSong时,调用父类的抽象方法speak
this.speak();
}
@Override
void speak() { //对于父类中的抽象方法,子类要重写给出具体实现
System.out.println("歌手唱歌");
}
}
public class Jiekou {
public static void main(String[] args) {
//实例化一个Singer类的对象
//调用Singer类所实现的接口Sing中的singSong方法,
//实例化一个Boy类对象,将其作为参数传递给singSong方法
new Singer().singSong(new Boy());
//singSong的参数类型为People,接收boy后自动转换
//转换后执行当前类的speak方法,当前类为Singer,因此执行”歌手唱歌“
}
}
--------------------------------------------------
运行结果:
歌手唱歌
可以看到,编写接口的方式和类很相似。但是接口不是类。
3.2 实现接口的注意点
类(实现接口)需要(重写接口)中声明的抽象方法。但是重写接口中声明的方法时,需要注意以下规则:
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
在实现接口时也应注意一些规则:
- 一个类可以同时实现多个接口,将接口名依次放在
implements关键字
后面,类里面要重写所有接口的抽象方法。 - 一个类只能继承一个类,但是能实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比较相似。
5. 接口的继承
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字
,子接口继承父接口的方法。
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
//实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
//Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。
public interface Hockey extends Sports
{
public void homeGoalScored();
public void visitingGoalScored();
public void endOfPeriod(int period);
public void overtimePeriod(int ot);
}
//java支持多继承,因此下面语句也是合法的
public interface Hockey extends Sports, Event
七、内部类
1.1 什么是内部类?
内部类就是在一个类的内部再定义一个类。比如,A类中定义了一个B类,则B类相对于A类来说称为内部类,A类相对于B类来说就是一个外部类。
使用内部类的好处:每个内部类都能独立地继承一个(接口的)实现,无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
使用内部类最大的优点:解决多重继承的问题
- 内部类提供了更好的封装,除了该外围类,其他类都不能访问。
1.2 内部类主要分为:
内部类分类
-
成员位置:在成员位置定义的类,被称为成员内部类
-
局部位置:在局部位置定义的类,被称为局部内部类
-
成员内部类
-
静态内部类
-
局部内部类
-
匿名内部类
内部类访问特点
- 内部类可以直接访问外部类成员,包括私有的
- 外部类要访问内部类成员,需先创建对象
public class Outer {
int num = 10;
private int a = 100;
//定义成员内部类
class Inner {
int b = 109;
public void innerShow() {
System.out.println("内部类的show方法");
}
//内部类可以直接访问外部类的成员,包括私有
public void innerTest(){
System.out.println(num);
System.out.println(a);
outerShow();
outerTest();
}
}
public void outerShow() {
System.out.println("这是外部类的show方法");
}
private void outerTest() {
System.out.println("这是外部类的show方法");
}
//外部类,想要访问内部类的成员,得创建内部类的对象
public void method(){
//创建内部类的对象
Inner inner = new Inner();
System.out.println(inner.b);
inner.innerShow();
}
}
//测试类
public class MyTest {
public static void main(String[] args) {
Outer outer = new Outer();
System.out.println(outer.num);
outer.outerShow();
System.out.println("----------------");
//使用成员内部类的属性和方法
//创建成员内部类的语法
Outer.Inner inner=new Outer().new Inner();
System.out.println(inner.b);
inner.innerShow();
System.out.println("---------------");
outer.method();
}
}
//输出
10
这是外部类的show方法
----------------
109
内部类的show方法
---------------
109
内部类的show方法
成员内部类
- 访问格式:外部类名.内部类名 变量名 = new 外部类名().new 内部类名();
//定义类
class Body {//外部类,身体
private boolean life= true;//生命状态
public class Heart { //内部类,心脏
public void jump() {
System.out.println("心脏噗通噗通的跳")
System.out.println("生命状态" + life); //访问外部类成员变量
}
}
}
public static void main(String[] args) {//访问内部类
//创建内部类对象
Body.Heart bh = new Body().new Heart();
//调用内部类中的方法
bh.jump();
}
成员内部类的修饰符
private 为了保证数据的安全性
static 为了方便访问数据
注意:静态内部类访问的外部类数据必须用静态修饰,成员方法可以是静态的也可以是非静态的
class Outer {
public int num = 10;
class Inner {
public int num = 20;
public void show() {
int num = 30;
System.out.println(num); //30
System.out.println(this.num); //20
System.out.println(new Outer().num); //10
System.out.println(Outer.this.num);// 和上面new Outer().num一个意思
}
}
}
class InnerClassTest {
public static void main(String[] args) {
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
局部内部类
局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问(在方法内部定义类)
- 定义格式
class 外部类 {
修饰符 返回值类型 方法名(参数) {
class 内部类 {
//其他代码
}
}
}
访问方式
在外部类方法中,创建内部类对象,进行访问
package com.inner;
public class Demo02 {
int a = 100;
public void show(int a ){
int num =0;
class nei{
public void neiShow() {
//局部内部类,访问外部类的局部变量,局部变量必须加上final修饰,JDK1.8 默认就加上了
System.out.println(num);
System.out.println(a);
}
}
nei nei=new nei();
nei.neiShow();
}
public static void main(String[] args) {
Demo02 demo02= new Demo02();
demo02.show(55);
}
}
----------------------------------
0
55
匿名内部类
-
匿名内部类的作用:临时定义某一指定类型的子类 ,定义后即刻创建刚刚定义的这个子类的对象
-
格式:
new 父类或接口(){
//进行方法重写
};
public static void main(String[] args) {
//匿名内部类:是局部内部类的简写
//匿名内部类,本质上是一个对象,是谁的对象,是实现了该接口或继承了该抽象类的子类对象
new AA(){
@Override
public void show() {
System.out.println("重写了show方法");
}
}.show();
}
}
abstract class AA{
public abstract void show();
}
//输出:重写了show方法
Java权限修饰符
一、四种权限修饰符
private(私有的) , 默认 , protected(受保护的) , public(公共的)
本类 同一个包下(子类和无关类) 不同包下(子类) 不同包下(无关类)
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
二、类及其组成所使用的常见修饰符
- 修饰符
- 权限修饰符:public、protected、默认、private
- 状态修饰符:static、final
- 抽象修饰符:abstract
- 修饰类的关键字
- 权限修饰符:默认修饰符,public
- 状态修饰符:final
- 抽象修饰符:abstract
- 修饰成员变量的关键字
- 权限修饰符:private、默认的、protected、public
- 状态修饰符:static,final
- 修饰成员变量的关键字
- 权限修饰符:private、默认的、protected、public
- 状态修饰符:static、final
- 修饰构造方法的关键字
- 权限修饰符:private、默认的、protected、public
- 修饰成员方法的关键字
- 权限修饰符:private、默认的、protected、public
- 状态修饰符:static、final
- 抽象修饰符:abstract
- 除此以外的组合规则
- 成员变量:public static final (接口)
- 成员方法:public static
public abstract
public final