Java第八课

Java第八课

一、super

  • super的意思是超级的,主要是和父类有关

  • 用法

    1. 调用父类的构造方法

      如果父类有默认构造方法,则可以不用super,但是,如果父类只有有参构造方法,此时,在创建子类对象时,在子类的构造方法中就要显示的调用super构造方法

      class Father{}
      Son son = new Son()
      执行new Son()时先执行new Father();
      以上代码是默认构造方法,JVM可以自动调用,用不上super
      真实运行时这样的:
      class Son extends Father{
      public Son(){
      super();
      }
      }

      -- 以上是默认的构造方法,如果父类没有默认构造方法,就要显示调用,此时使用super。

      public class Father {
         public Father(String name) {
             System.out.println("father" + name);
        }
      }
      class Son extends Father{

         public Son(String name) {
             super(name);
        }
      }

      -- 如果父类的构造方法不是默认的,子类必须要有和它匹配的构造方法,重点是:在子类中使用super调用父类的构造方法,并且传入参数。

      -- super在子类构造方法中必须是第一行代码。

    2. 用super调用子类覆盖的父类的方法

      比如:父类有say(),子类也有say(),并且say被覆盖,如果在子类中想要调用父类的say方法,只能使用super.say();

      public class Father {
         public Father(String name) {
             System.out.println("father" + name);
        }

         public void say() {
             System.out.println("father say");
        }

         /**
          * 调用this,此时this是谁,多态的知识点,不管this代码在哪里,关键是看声明,
          * Father son = new Son(),指向的是son的say
          * Father father = new Father(),指向的是father的say
          *
          */
         public void fatherTest() {
             this.say();
        }
      }
      class Son extends Father{

         public Son(String name) {
             super(name);
        }

         @Override
         public void say() {
             System.out.println("son say");
        }

         public void test() {
             say();
             super.say();// 用super调用被重写的父类的方法
        }

         public static void main(String[] args) {
      /*       Son son = new Son("son");
             son.test();*/
             Father son = new Son("son");
             // son.test();
             // 在编译器看来,此时的son的身份是father,son中具有father的成员,没有子类的成员
             son.fatherTest();
        }
      }
  • 多态:this.say(),关键是看声明的时候创建的是谁的实例,

二、instanceof和强转

instanceof运算符是特殊的运算符,可以判断某个对象是否某个类的实例。 如果B是A的子类,则: A obj = new B(); 赋值号= 左边是大类型,基本类型,右边是子类型,则可以自然转换,如:Chinese obj = new Shanxi(); if (obj instanceof B) 则B b = (B)obj;当检查到obj实际身份是B时,可以还原其身份到B类型,但此时obj的外在身份依然是A,所以转换时还是要加括号进行强转,强转的前提是类型正确,比如C也是A的子类,上面的obj就不能强转成C,会报类型转换错误的异常。

三、接口

  • interface 类的行为规范

  • 类有什么用?实现某些业务,存储数据,传递数据(方法的参数)

    POJO,Java原始类,这样的类用来存储数据和传递数据,bean包,entify包(类似于这些放简单类的包)下都是POJO

    1. JDK8之前,接口中只有抽象方法和常量,接口中的所有的方法默认都是抽象的,所以在定义方法时不用写public和abstract。

      void say();//等价于public abstract void say();

      接口中的变量都是常量,因为变量会默认加上public static final,

      int UPDATE_SUCCESS = 1;// 等价于 public static final

      常量的命名要大写,单词和单词之间用“_”隔开

    2. JDK8开始,接口中有了默认方法,这些方法有方法体,方法用关键字default定义,接口不用来实现业务,只定义行为要求,需要做什么,具体实现细节由接口的实现类来完成。如果一个接口中有N个方法,实现类就要实现N个方法,如果没有实现所有的方法,则该类是抽象类。

      在JDK原码中,有大量的实现接口没有完全实现的抽象类,他们可以分层次的去实现.

      有的项目组接口的定义规则是以"I"开头,实现类以”impl“结束

      implement实现,impl是缩写

      java中的继承是单继承的,只能有一个父类,java中可以同时实现多个接口。

      public class Son extends Father implement IAnimal,IDao{

      }

      接口时不能创建实例的,接口可以使用多态的技术,具有父类的效果。接口中的方法是抽象的,抽象类中的方法是对接口中的方法的重写,这也体现出父类和子类的特点。

  • 接口特点

    1. 不能创建实例

    2. 只能定义常量

    3. 普通方法都为抽象方法

    4. default方法可以有方法体

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

  • 抽象类特点

    1. 抽象类不能创建实例

    2. 可以定义抽象方法和普通方法

    3. 单继承

  • 接口1和接口2中的方法相同,实现一个另外一个自动实现

  • 当接口1和接口2中有相同的方法,但是返回值不兼容,实现类无法实现这两个类。

  • 如果接口1和接口2的返回值兼容,即使不一样,实现类也可以同时实现两个方法。

结论:Java中的单继承是指类的单继承,接口可以多继承

接口继承多个接口时,多个接口中不能有冲突的方法存在

当一个类同时实现一个接口和继承一个父类时,父类和接口中的方法也不能冲突。

四、包

  • 包是用来管理类的,可以避免同名类的冲突,每个包有相应的功能,包下的类就是这相应功能的类。

    通常工程中的类有几大功能:

    控制器类,业务类,数据库类,POJO类

    根据这些功能建对应的包:controller包,service包,dao包,bean包

    不同的包下放同一类功能的类

    包的另一个功能,管理权限。

    修饰符,访问修饰符:private<default(不写)<protected<public

     类内部包内部继承包外(不继承)
    public OK OK OK OK
    protected OK OK OK NO
    default(不写) OK OK NO NO
    private OK NO NO NO

    包内:包里有A,B两个类,A中的public,protected,default成员都可以在B中访问,A中的private不可以

    继承:包1中有A,包2中有B,B类继承A类,B类只能访问A类中的public和protected,default和private不能访问,default只能在同一个包下互相访问,出了包不可以,protected因为继承的关系,在不同的包下可以访问。

    -- 如果父类和子类分别在不同的包下,父类中的default修饰的成员无法在子类中访问,但是protected可以访问

五、内部类

包1下定义一个类,该类不是public,是默认的,包2无法访问。

内部类:定义在一个类内部的类。它可以定义在一个类中的属性的区域或方法中,或一个代码块中,if,for

内部类可以有名字,可以没有名字(匿名内部类),匿名内部类多用于抽象类或接口的实例化(抽象类和接口本身是不能创建实例的,但是可以通过匿名内部类简介实现)

内部类的优点:它可以具有类的功能,但是只限于当前类使用,不对外,否则就定义成一个外部的类,可以组织代码,使得代码结构清晰。内部类可以绕开Java的单继承,如果外部类继承了一个类,而此时还想继承另一个类,就让内部类来继承它。

两点:第一点:别人不用,自己用;第二点:内部类可以定义成为方法来使用,但是方法有局限性,当一个方法完成不了时,需要定义成一个类,方法升级为内部类后,功能增强。

内部类可以访问外部类的数据(注意静态的使用,如果内部类是静态的,则情况复杂),静态内部类只能访问外部类的静态数据

分类:

  1. 成员内部类

    • 成员内部类

    • 静态成员内部类

    public class Outer {
       int id = 1;
       /**
        * 成员内部类
        */
       class Inner1{
           public void say() {
               System.out.println("Inner1 say");
          }
      }

       /**
        * 静态成员内部类
        */
       static class Inner2{
           public void say() {
               System.out.println("Inner2 say");
          }
      }
       public static void main(String[] args) {
           Outer outer = new Outer();
           // 访问类的成员
           System.out.println(outer.id);
           Outer.Inner1 inner1 = new Outer().new Inner1();
    //       inner1.say();\
           Outer.Inner2 inner2 = new Outer.Inner2();
           inner2.say();
      }
    }
  2. 方法内部类

        public void work() {
           /**
            * 方法内部类只能在方法内部使用
            */
           class Inner1{
               public Inner1(){
                   System.out.println("method Inner1 created");
              }
               void work() {
                   System.out.println("method Inner1 work");
              }
          }
           Inner1 inner1 = new Inner1();
           inner1.work();
      }
  3. 块内部类

    public void work2() {
       if (id > 0) {
           /**
            * 块内部类
            */
           class Inner1{
               public Inner1() {
                   System.out.println("if block Inner1 created");
              }
          }
           Inner1 inner1 = new Inner1();
      }
  }
  1. 匿名内部类

    public class Worker {
       private int age = 10;

       public void test() {
           AbstractWorker abstractWorker = new AbstractWorker() {
               int id;
               @Override
               public void work(String name) {
                   System.out.println("编号:" + id + age + "岁的" + name + "在工作");
              }
          };
           abstractWorker.work("Tom");
      }

       public static void main(String[] args) {
           Worker worker = new Worker();
           worker.test();
      }
    }
    abstract class AbstractWorker{
       /**
        * 工作
        * @param name 工人姓名
        */
       public abstract void work(String name);
    }



posted @ 2021-03-13 17:02  若你  阅读(42)  评论(0编辑  收藏  举报