Fork me on GitHub

接口、抽象类以及匿名内部类的学习

用IDEA学习Java的第八天

instanceof和类型转换

  • instanceof的作用就是判断左边对象是否是右边类的实例,判断对象是什么类型。

    System.out.println(A instanceof B);//判断对象A是否属于类B的类型,A和B必须是父子关系,否则编译报错
    
  • 类型转换

    1. 父类引用指向子类的对象

    2. 把子类转换为父类,向上转型:

      //Person为student的父类
      public class Application{
          public static void main(String[] args){
            //类型转换:子类转换为父类
            //子类转换为父类,可能会丢失一些自己的方法 
              Student student=new Student();
              Person person=student;
              
          } 
      }
      
    3. 把父类转换为子类,向下转型强制转换

      //Person为student的父类
      //eat()方法为Student类所独有
      public class Application{
          public static void main(String[] args){
              //类型转换:父类转换为子类
              Person person=new Student();
              Student student=person;
              student.eat;
          }
      }
      
  • 代码实例

    主方法:

    package com.zjl.oop.Demo05;
    
    public class Application {
        public static void main(String[] args) {
            Person student = new Student();
            // Object>String
            // Object>Person>Teacher
            // Object>Person>Student
            // instance判断对象是什么类型
            // instanceof判断左边对象是否是右边类的实例
            //System.out.println(A instanceof B);A和B必须是父子关系
            System.out.println(student instanceof Object);//true
            System.out.println(student instanceof Person);//true
            System.out.println(student instanceof Student);//true
            System.out.println(student instanceof Teacher);//false
            //System.out.println(student instanceof String);//编译错误
            System.out.println("*********************");
            Object student1=new Student();
            System.out.println(student1 instanceof Object);//true
            System.out.println(student1 instanceof Person);//true
            System.out.println(student1 instanceof String);//false
            System.out.println(student1 instanceof Student);//true
            System.out.println(student1 instanceof Teacher);//false
            System.out.println("*********************");
            Student student2=new Student();
            System.out.println(student2 instanceof Object);//true
            System.out.println(student2 instanceof Person);//true
            System.out.println(student2 instanceof Student);//true
    //      System.out.println(student2 instanceof String);//编译错误
    //      System.out.println(student2 instanceof Teacher);//编译错误
            //高                低           高转低需强制类型转换
            Person person=new Teacher();
            ((Teacher)person).play();//强制类型转换
    
           //低转高 子类转换为父类就会丢失一些方法
            Teacher teacher=new Teacher();
            Person person1=teacher;
            person1.run();
    
        }
    }
    
    

    Person类:

    package com.zjl.oop.Demo05;
    
    public class Person {
        public void run(){
            System.out.println("奔跑吧!sao年");
        }
        public void eat(){
            System.out.println("我爱徐大sao!!!");
        }
    
    
    }
    
    

    Student类:

    package com.zjl.oop.Demo05;
    
    public class Student extends Person{
    }
    
    

    Teacher类:

    package com.zjl.oop.Demo05;
    
    public class Teacher extends Person{
        public void play(){
            System.out.println("打篮球了");
        }
    }
    
    

static关键字

  • static关键字的主要用途:通过static修饰的方法或者成员变量不需要对象来进行访问,只要类被加载了,就可以通过类名进行访问。
package com.zjl.oop.Demo06;

public class Student {
    //定义一个静态成员变量  多线程可用到
    private static int age;
    //定义一个非静态成员变量
    private int score;
    public static void run(){

    }
    public void go(){}

    public static void main(String[] args) {
        Student student=new Student();
        run();
        student.go();
        age=30;
        System.out.println(age);
        student.score=100;
        System.out.println(student.score);
    }

}

  • static代码块

    static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

package com.zjl.oop.Demo06;



public class Person {
    {
        System.out.println("输出一个匿名代码块");
    }
    //静态代码块只执行一次
    static{
        System.out.println("输出第一个静态代码块");
    }
    static{
        System.out.println("输出第二个静态代码块");
    }

    public Person() {
        System.out.println("输出构造方法");
    }

    public static void main(String[] args) {
        Person person=new Person();
        System.out.println("*******************");
        Person person1=new Person();
    }
}

运行结果:

输出第一个静态代码块
输出第二个静态代码块
输出一个匿名代码块
输出构造方法


输出一个匿名代码块
输出构造方法

Abstract抽象类

  • abstract修饰符可以用来修饰方法,也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法,但是由抽象的方法的类一定要声明为抽象类。
  • 抽象类不能使用new关键字来创建对象,它是用来让子类继承的。
  • 抽象方法,只有方法声明,没有方法实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类中没有实现的抽象方法,并且该子类中不能有抽象方法,否则该子类也必须是抽象类,让子子类去实现抽象类的抽象方法。
  • 抽象类可以有构造方法,只是不能直接创建抽象类的实例对象而已。在继承了抽象类的子类中通过super()或super(参数列表)调用抽象类中的构造方法。
package com.zjl.oop.Demo07;
//抽象类
public abstract class Action {
    //抽象方法,只有方法名字,没有方法的实现

    public Action() {
        System.out.println("我是抽象类的构造方法");
    }

    public abstract void doSomething();

    //抽象类的特点
    //1、不能new这个抽象类,只能靠子类去实现它
    //2、抽象类中可以写普通的方法
    //3、抽象方法必须在抽象类中
}

package com.zjl.oop.Demo07;

public class A extends Action{
    public A() {
        super();
    }
    @Override
    //重写抽象方法
    public void doSomething() {

    }

    public static void main(String[] args) {
        A a=new A();

    }

}

编译结果:

我是抽象类的构造方法

抽象类中的构造方法:

package com.zjl.oop.Demo07;

public abstract class Test {
    int a=8;
    public Test(){
        a=6;
    }
    public Test(int i){
        a=i;
    }
    public abstract void Test();

}
class B extends Test{

    public B(){
        super();
    }
    public B(int a){
       super(a);
    }

    @Override
    public void Test() {

    }

    public static void main(String[] args) {
    B b=new B();
    B b1=new B(10);
    System.out.println(b.a);
    System.out.println(b1.a);
    }
}

接口

接口就是规范,定义的是一组规则

声明接口的关键字是interface,接口也是一种特殊的类,一个接口中包括永远不变的常量和没有方法体的抽象方法。一个接口就是描述一种能力,接口的作用就是告诉类,你要实现我这种接口代表的功能,你就必须实现某些方法,我才能承认你确实拥有该接口代表的某种能力。

编程就是约束和实现分离:面向接口编程

重点:

  1. *我们不能直接去实例化一个接口,因为接口中的方法都是抽象的,是没有方法体的*,这样怎么可能产生具体的实例呢?但是,*我们可以使用接口类型的引用指向一个实现了该接口的对象,并且可以调用这个接口中的方法*。因此,上图中最后的方法调用我们还可以这样写:(实际上就是使用了Java中多态的特性)

    USB usb=new UpanServiceImpl();
        usb.read();
        usb.write();
    USB usb1=new JanpanServiceImpl();
        usb1.write();
        usb1.read();
    
  2. 一个类可以实现不止一个接口。

  3. 一个接口可以继承于另一个接口,或者另一些接口,接口也可以继承,并且可以多继承。

  4. 一个类如果要实现某个接口的话,那么它必须要实现这个接口中的所有方法。

接口的作用:
1、定义一个约束。
2、定义一些方法,让不同的人去实现这些方法。
3、接口中的默认的方法都是public abstract类型的
4、接口中定义的常量都是public static final类型
5、接口不能被实例化,接口中没有构造方法
6、implements可以实现多个接口
7、在实现接口中方法时,必须要重写接口中的方法。

代码实例:

定义一个UserService接口:

package com.zjl.oop.Demo08;
//定义的关键字是interface
public interface UserService {
    //接口中定义的常量是静态的
    public static final int age=99;
    //接口中的所有定义都是抽象的  public abstrat
    void add(String name);
    void delete(String name);
    void update(String name);
    void query(String name);
}
/*
接口的作用:
1、定义一个约束。
2、定义一些方法,让不同的人去实现这些方法。
3、接口中的默认的方法都是public abstract类型的
4、接口中定义的常量都是public static final类型
5、接口不能被实例化,接口中没有构造方法
6、implements可以实现多个接口
7、在实现接口中方法时,必须要重写接口中的方法。
 */

定义一个实现接口的类:

package com.zjl.oop.Demo08;
//实现接口
//实现了接口的类就需要重写接口中的方法
//利用接口我们可以实现多继承
public class UserServiceImpl implements UserService,TimeService{
    String name;
    public UserServiceImpl(String name){
        this.name=name;
    }

    @Override
    public void add(String name) {
        System.out.println("增加了"+name);
    }

    @Override
    public void delete(String name) {
        System.out.println("删除了"+name);
    }

    @Override
    public void update(String name) {
        System.out.println("更新了"+name);
    }

    @Override
    public void query(String name) {
        System.out.println("查到了"+name);
    }

    @Override
    public void time() {

    }
}

主方法:

package com.zjl.oop.Demo08;

public class Application {
    public static void main(String[] args) {
        UserServiceImpl user=new UserServiceImpl("周乐乐");
        user.add(user.name);
        user.delete("周一");
        user.query("周二");
        user.update("周三");
    }
}

多态补充

一个父类会有很多子类,子类会有很多状态,称之为多态。例如:动物类作为一个父类,狗类和鸡类继承动物类之后,狗类会发出吠叫,而鸡类会发出鸡鸣,子类会产生多种状态,为减少代码,使得代码变得更加简洁,出现了多态。

Animal animal=new Gog();      //向上转型,父类类型的引用指向子类的对象
Animal animal=new Chicken();  //向上转型,父类类型的引用指向子类的对象

匿名内部类

匿名内部类的定义方法

  1. 操作符:new;
  2. 一个要实现的接口或要继承的类,案例一中的匿名类实现了HellowWorld接口,案例二中的匿名内部类继承了Animal父类;
  3. 一对括号,如果是匿名子类,与实例化普通类的语法类似,如果有构造参数,要带上构造参数;如果是实现一个接口,只需要一对空括号即可;
  4. 一段被"{}"括起来类声明主体;
  5. 末尾的";"号(因为匿名类的声明是一个表达式,是语句的一部分,因此要以分号结尾)。

实现接口的匿名内部类

package com.oop.demo12;

public class Test {
    public static void main(String[] args) {
        //没有名字初始化类,不用将实例保存在变量中
        new Apple().eat();

        //匿名内部类实现UserService接口
        UserService userService=new UserService(){

            @Override
            public void run() {
                System.out.println("跑步啦");
            }
        };
        userService.run();
    }
}
class Apple{
    public void eat(){
        System.out.println("我要吃苹果");
    }
}
interface UserService{
      void run();
}
posted @ 2020-11-21 10:15  乐二啊  阅读(285)  评论(0)    收藏  举报