JAVA复习 面向对象高级编程Day12 接口 内部类

面向对象高级编程Day12

10.7接口

10.7.1接口快速入门

package com.interface01;

public interface usb {//接口
    //接口,规定接口的相关方法 ,即规范
    public void start();
    public void stopp();

}
package com.interface01;

public class camera implements  usb {//实现接口,就是把接口方法实现
    
    public void start() {
        System.out.println("相机开始工作....");
    }

    
    public void stopp() {
        System.out.println("相机停止工作...");
    }
}
package com.interface01;
//phone要实现usb接口
//phone类需要实现usb接口    规定/声明的方法
public class phone implements  usb {
    
    public void start() {
        System.out.println("手机开始工作...");
    }

    
    public void stopp() {
        System.out.println("手机停止工作...");
    }
}
package com.interface01;

public class computer  {
    //编写方法,让计算机工作
    public  void work(usb usb1){
        //通过接口来让计算机工作
        usb1.start();
        usb1.stopp();
    }
}
package com.interface01;

public class interface01 {
    public static void main(String[] args) {
        //创建手机,相机对象
        camera camera1 = new camera();
        phone phone1 = new phone();
        //创建计算机
        computer computer1 = new computer();
        computer1.work(phone1);//把手机接入到计算机
        computer1.work(camera1);//把相机接入到计算机
    }
}

10.7.2接口的简单介绍

接口就是给出一些没有实现的方法封装到一起,到某个类要使用的时候,在根据具体情况把方法写出来

语法:
interface 接口{
//属性
//方法(抽象方法,默认实现方法default,静态方法)
}
class 类名 implements 接口{
自己属性;
自己方法
必须实现的接口的抽象方法
}

注:
在接口中,抽象方法可以省略abstract关键字
JDK7之前接口里的所有方法都没有方法体,即都是抽象方法
JDK8之后接口类可以有静态方法,,也就是说接口中可以有方法的具体实现,JDK8以后,可以有默认实现方法,需要使用default关键字修饰

10.7.3接口的注意事项和使用细节

1、接口不能被实例化

2、接口中所有的方法是public方法,接口中抽象方法,可以不用abstract修饰

3、一个普通类实现接口,就必须将该接口的所有方法都实现

4、抽象类实现接口,可以不用实现接口的方法

5、一个类同时可以实现多个接口

6、接口中的属性,只能是final的,而且是public static final 修饰符
###############################################################
接口中的所有属性都是静态的,公开的,不用加载类方法
接口里面的 int n1=10;//等价于public static final int n1=10;
###############################################################

7、接口中属性的访问形式接口名.属性名
###############################################################

package com.interface01;

public class interface02 {
    public static void main(String[] args) {
        B b =new B();
        System.out.println(b.a);
        System.out.println(A.a);
        System.out.println(B.a);
    }
}
interface  A{
    int a=23;//在这里等价于public static final int  a=23;
}
class B implements  A{

}

此代码的结果为3个23

###############################################################

8、一个接口不能继承其他的类,但是可以继承多个别的接口
interface A extends B,C{}

9、接口的修饰符只能是public和默认,这点和类的修饰符是一样的

10.7.4实现接口VS继承类

举个栗子
猴子和小猴子的关系就是继承的关系,继承的关系就是自然而然地接受父类的能力
但是小猴子要想实现飞翔的功能,就要去实现小鸟飞行的功能,想要游泳,就要是实现鱼的功能;而接口地话是本身所不拥有的,需要在进行实现

接口和继承解决的问题不同
继承的价值主要在于:解决代码的复用性和可复用性
接口的价值主要在于:设计号各种规范方法,让其他类自己去进行实现

接口比继承更加灵活:继承是is-a的关系;接口只需要满足like-a的关系

接口在一定程度上实现代码解耦【接口规范性+动态绑定】

10.7.5接口的多态

1、多态参数,在快速入门中的案例中就体现了
在这里接受了手机对象,又接受了相机对象,就体现了接口;多态

package com.interface01;

public class interface01 {
    public static void main(String[] args) {
        //创建手机,相机对象
        camera camera1 = new camera();
        phone phone1 = new phone();
        //创建计算机
        computer computer1 = new computer();
        computer1.work(phone1);//把手机接入到计算机
        computer1.work(camera1);//把相机接入到计算机
    }
}
package com.interface01;

public class interface02 {
    public static void main(String[] args) {
        //接口体现的多态
        //接口类型的变量if01可以指向实现了IF接口的类对象实例
         IF  if01 =new Monster();
         if01  = new Car();

        //继承体现的多态
        //父类类型变量a可以指向继承AAA的子类的对象实例
        AAA a = new BBB();
        a= new CCC();
    }
}
interface  IF{ }
class Monster implements  IF {}
class Car implements  IF{}
class AAA{}
class BBB extends  AAA{}
class CCC extends  AAA{}

2、多态数组
接口型数组,可以指向实现了它的方法的对象实例
向下转型

package com.interface01;

public class interface02 {
    public static void main(String[] args) {
        //动态数组
        IF[] if01 = new IF[2];
        if01[0]=new Monster();
        if01[1]=new Car();
        for (int i=0;i<if01.length;i++){
            if01[i].work();//动态绑定
            //在此处需要进行类型的向下转型
            if (if01[i] instanceof  Monster){
                //判断运行类型是否为Monster
                ((Monster) if01[i]).call();
            }
        }
    }
}
interface  IF{
    void work();
}
class Monster implements  IF {
    public  void call(){
        System.out.println("被调用....");
    }

    @Override
    public void work() {
        System.out.println("恶魔正在工作中....");
    }
}
class Car implements  IF{
    @Override
    public void work() {
        System.out.println("汽车正在工作中....");
    }
}

3、接口存在多态传递
接口类型的变量可以指向,实现了该接口类的对象实例

package com.interface01;

public class interface03 {
    public static void main(String[] args) {
        //接口类型的变量可以指向,实现了该接口类的对象实例
        IG ig =new teacher();
        //如果IG继承了IH 接口,而teacher类实现了IG 接口
        //那么实际上就相当于teacher也实现了IH 接口
        //在这里就体现了接口多态的多态传递现象
        IH ih = new teacher();
    }
}

interface IH{
    void hi();
}
interface IG extends IH{ }
class teacher implements  IG{
    @Override
    public void hi() {
    }
}

10.8内部类

10.8.1内部类的基本介绍

一个类的内部又完整的嵌套l另一个类结构,被嵌套的类称为内部类
嵌套其他类的类称为外部类
内部类的最大特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系

10.8.2基本语法

class  Outer{//外部类
    class Inner{//内部类
    }
}
class Other{
    //外部其他类
}

类的五大成员:属性,方法,构造器,代码块,内部类

10.8.3内部类的分类

定义在外部类局部位置上(比如方法内)
局部内部类(有类名)
匿名内部类(没有类名!!!!,重点)

定义在外部类的成员位置上(属性和方法的位置上)
成员内部类(没用static修饰)
静态内部类(使用static修饰)

10.8.3.1局部内部类细节说明 (本质就是一个类)

定义是指定义在外部类的局部位置上,比如方法中,并且有类名
说明:
A:可以直接访问外部类的所有成员,包含私有的

B:不能添加访问修饰符,因为它的低位就是一个局部变量,局部变量是不能使用修饰符的,但是可以使用final修饰,因为局部变量也可以使用final

C:作用域:仅仅在定义它的方法或代码块中

D:局部内部类——访问——外部类的成员【直接访问】

E:外部类——访问——局部内部类的成员
创建对象,再访问,必须再作用域内

F:外部其他类——不能访问——局部内部类(因为局部内部类地位是一个局部变量)

G:如果外部类和局部内部类的成员重名时,默认遵守就近原则,如果想访问外部类的成员,则可以使用**(外部类名.this.成员)**去访问

10.8.3.2匿名内部类(本质还是类,内部类,该类没有名字,是一个对象) 匿名内部类适合用于只用一次的

1、 匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
基本语法

 new/接口  (参数列表){
 类体
 };
interface  A{//接口
    public  void cry();
}

//基于接口的匿名内部类

class outer02{//外部类
    private  int n1 =10;//属性
    public void method(){//方法

        //基于接口的匿名内部类
        //需求:想使用IA接口,并创建对象
        //传统方式,写一个类,实现该接口,并创建对象
        //Tiger类只是使用一次,后面不再使用
        //可以使用匿名内部类来简化开发
        //tiger1的编译类型是接口类型
        //tiger1的运行类型是匿名内部类  XXXX=>outer02$1
        //匿名内部类使用一次就不能再运行
        //对象可以反复使用
        /*
             底层会分配类名
            class XXXX implements A{
                  @Override
                  public void cry() {
                        System.out.println("老虎.....");
                 }
            }

         */
        A tiger=new A(){
            public void cry() {
                System.out.println("老虎.....");
            }//匿名内部类的使用
        };
        System.out.println("tiger的运行类型为"+tiger.getClass());
        //getClass就是获取运行类型
        tiger.cry();
    }
}

//基于类的匿名内部类

###############################################################

注:这里存在的匿名内部类其实是子类,而并非是原来的类,由于是类所以是继承关系,而上面由于是接口所以是实现

###############################################################

public class anon {
    public static void main(String[] args) {
        outer02 outer02 = new outer02();
        outer02.method();
    }
}
//基于类的匿名内部类
        //father编译类型Father
        //father运行类型outer02$2
        //底层会创建匿名内部类
        /*  这里是类和类的关系,所以继承,不是实现
          class  outer02$2 extends Father{
          }
         */
        //同时也返回了匿名内部类outer02$2的对象
        //注:这里是新的类,不再是Father类
 class outer02{//外部类
    private  int n1 =10;//属性
    public void method(){//方法
    Father father=new Father("jack"){
         public void test() {
                System.out.println("匿名内部类重写了方法");
            }
    };
     System.out.println("father对象的运行类型="+father.getClass());
     father.test();
  }
}
class  Father{
    public  Father(String name){//构造器
    }
    public  void   test(){//方法
    }
}

2、匿名内部类的语法比较,匿名内部类是一个类的定义
同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征
3、可以直接访问外部类的所有成员,包含私有的
4、不能添加访问修饰符,因为它的地位就是一个局部变量
5、作用域:仅仅在定义它的方法或者代码块中
6、匿名内部类——访问——外部成员【直接访问】
7、外部其他类——不能访问——匿名内部类【局部变量】
8、如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问

###############################################################

匿名内部类的最佳实践
可以当作实参进行传递

package com.charpter10;

public class anon {
    public static void main(String[] args) {
        f1(new IL(){
            public void show() {
                System.out.println("这是将匿名内部类传入");
            }
        });
    }
    //静态方法,形参是接口类型
    public  static void f1(IL il){
          il.show();
    }
}
interface  IL{
    void show();
}

###############################################################

10.8.3.3成员内部类

成员内部类是定义在外部类的成员位置,并且没有static修饰
1、可以直接访问外部类的所有成员,包含私有的
2、可以添加任意访问修饰符,因为它的本质就是一个成员
3、作用域和外部类的其他成员一样,为整个类体,在外部类的成员方法中创建成员内部类对象,再调用方法
4、成员内部类——访问——外部类【直接访问,因为是一个成员】
5、外部类——访问——内部类【先创建一个内部类的对象再进行访问】
6、外部其他类——访问——成员内部类

3种方式
第一种
在这里将inner()当作一个成员来对待
outer1.new inner();相当于把new inner()当做是outer的成员

  outer outer1 = new outer();
  outer.inner inner1 = outer1.new inner();
package com.charpter10.menber;

public class memberclass {
    public static void main(String[] args) {
    //第一种
        outer outer1 = new outer();
        outer.inner inner1 = outer1.new inner();
        //外部类名.内部类名 【名称】= 外部类对象.new 内部类
        //外部类的对象去新建了一个内部类
        //在这里将inner()当作一个成员来对待
        //outer1.new inner();相当于把new inner()当做是outer的成员
    }
}
class outer{
    private  int n1=10;
    public  String name ="张三";
    private  void hi(){
        System.out.println("hi()方法....");
    }
    public  class inner{
        private  double sal=99.8;
        public  void say(){
            System.out.println("n1="+n1+"\tname="+name);
            hi();
        }
    }
}

第二种
在外部类中,编写一个方法,可以返回一个inner的对象

outer outer1 = new outer();
//第二种,在外部类中,编写一个方法,可以返回一个inner的对象
outer.inner getinner02 = outer1.getinner();
getinner02.say();
package com.charpter10.menber;

public class memberclass {
    public static void main(String[] args) {
        outer outer1 = new outer();
        //第二种,在外部类中,编写一个方法,可以返回一个inner的对象
        outer.inner getinner02 = outer1.getinner();
        getinner02.say();
    }
}
class outer{
    private  int n1=10;
    public  String name ="张三";
    private  void hi(){
        System.out.println("hi()方法....");
    }
    public  class inner{
        private  double sal=99.8;
        public  void say(){
            System.out.println("n1="+n1+"\tname="+name);
            hi();
        }
    }
    //返回一个inner()的实例
    public  inner getinner(){
        return new inner();
    }
}

第三种
双重new
7、如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类成员,则可以使用(外部类名.this.成员

10.8.3.4静态内部类

1、静态内部类是定义在外部类的成员位置,并且有static修饰
2、可以添加任意访问修饰符,但不能直接访问非静态成员,因为它的地位就是一个成员
3、作用域:同其他的成员,为整个类体
4、静态内部类——访问——外部类【直接访问所有静态成员】
5、外部类——访问——静态内部成员【创建对象,再访问】
6、外部其他类——访问——静态内部类
方式一:先创建一个外部类的实例,然后用new 实例.内部类去创建
方式二:编写一个方法,可以返回一个静态内部类的实例,去调用
方式三:编写一个静态方法,可以返回一个静态内部类的实例,去调用
方式四:可以不用创建外部类的实例,直接调用静态方法,返回一个静态内部类
7、如果外部类和静态内部类的成员重名时,静态内部类访问的时候,默认遵顼就近原则,如果想访问外部类的成员,可以使用(外部类名.成员)去访问

10.8.3.5简单小结

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值