Java基础之初识面向对象(包、继承、多态、抽象类、接口)

1、包

  1. 什么是包?

    包是组织类的一种形式

  2. 为什么要用包?

    保证类的唯一性,使得类名可以重复

  3. 常规导包

    a、import关键字

    导包可以导入特定的类名,也可以用通配符,如

    import java.sql.Date;//特定
    import java.util.*;//通配符
    

    b、注意事项

    • 在java中使用通配符并不是导入包下所有的类,而是在本类中用到了哪个类就导入哪个类

    • 虽然通配符很方便,但可能会发生冲突,如下

      import java.util.*;
      import java.sql.*;
      ...
      Date date = new Date();
      // 编译出错Error:对Date的引用不明确;
      //这是因为 java.sql 包下和 java.util 包下都有 Date 这个类,编译器不知道导入哪个Date类
      

      这上述这种情况下,就要用完整类名import java.util.Date;

    • java.lang包下的类是自动导入,但是lang包下嵌套的包中的类要手动导入

    • import java .* ; 这是不允许的,因为在java语言中规定,这里的*只代表某些类的名字。

    c、常见系统包

    • java.lang:系统常用基础类 (String、Object)
    • java.lang.reflflect:java 反射编程包
    • java.net:进行网络编程开发包
    • java.sql:进行数据库开发的支持包
    • java.util:是java提供的工具程序包
    • java.io:I/O编程开发包
  4. 静态导入

    import static用于导入指定类的某个静态成员变量、方法或全部的静态成员变量、方法。

  5. 包的访问控制权限

    privatedefaultprotectedpublic
    本类
    同包×
    异包子类××
    异包非子类×××

2、继承

  1. 面向对象的基本特征?

    ​ 封装继承多态

  2. 继承的作用?

    继承是对共性的抽取,主要是为了代码重用,体现在代码上就是使用extends关键字实现继承。此外,也正是因为有了继承,才有方法覆盖和多态机制

  3. 什么时候可以继承?

    满足" is a "关系

    比如 “cat is a animal” , " dog is a animal ",这种情况下cat和dog就可以继承Animal

    继承时,cat/dog被称为子类,派生类,Animal被称为父类、基类或超类

    所有类默认继承Object类(老祖宗类)

  4. 语法规则?

    1. java中只支持单继承,但支持实现多接口

    2. 对于父类中的私有字段和方法,子类可以继承,但是无法访问,可以通过get、set访问父类中的私有属性

    3. 子类会继承父类的所有 public 的字段和方法,protected和default会视情况继承(包含类方法)

    4. 构造方法不会继承

    5. 子类继承父类,必须帮助父类先构造

      构造器的执行顺序是从根部的基类开始,一直到距离本类最近的父类,最后执行本类的构造器

      class A {
          public A() {}
      }
      class B extends A {
          public B() {}
      }
      class C extends C {
          public C() {}
      }
      C c = new C();
      //实例化C对象,依次调用的顺序是A()->B()->C()方法
      

      也就是实例化子对象,会先调用父类型的构造方法初始化父类的那部分特征。

    6. 对于静态变量,在子类中修改会影响到父类

  5. final关键字

    • final修饰的类不能被继承,叫密封类

    • final修饰的方法无法覆盖

    • final修饰的变量只能赋一次值

    • final修饰的引用一旦指向某个对象,则不能再重新指向其它对象,但该引用指向的对象内部的数据是可以修改的

    • final修饰的实例变量必须手动初始化,不能采用系统默认值

    • final修饰的实例变量一般和static联合使用,称为常量

      public static final double PI = 3.1415926;

  6. super关键字?

    6.1、super能出现在实例方法和构造方法中

    6.2、super的语法是:“super.”、“super()”

    6.3、super不能使用在静态方法中。

    6.4、super . 大部分情况下是可以省略的。那么super .什么时候不能省略呢?
    父类和子类中有同名属性,或者说有同样的方法,想在子类中访问父类的,super . 不能省略。

    6.5、super的使用:

    super.属性名			//【访问父类的属性】
    super.方法名(实参)		//【访问父类的方法】
    super(实参)			//【调用父类的构造方法】
    

    6.6、super在内存图中体现:
    super在内存图中的体现
    可以看出,在多级继承中,super只会指向最近的基类

  7. super和this的区别?

    super的使用基本与this一致,主要区别在于

    1. super代表父类对象的引用
    2. this代表本类对象的引用
    3. super虽然代表子类的父类对象,但是不持有父类对象的地址值,而this作为当前子类对象
    4. this()和super()都只能在构造方法的第一行
    5. super和this都市依赖当前对象的,不能用在static方法中
  8. java实现多继承的三种方式

    • 内部类
    • 实现接口
    • 一个父类继承另一个父类

protected修饰的属性a,对于不同包的子类中,只能通过super访问a,不能通过当前对象访问a,

子类和父类中的字段同名时,也符合就近原则,要想访问父类中的那个同名字段,必须使用super

class Animal {
    protected String name;

    public Animal(String name) {
        this.name = name;
    }
}

class Cat extends Animal {
    public Cat() {
    }//报错
}

3、多态

  1. 何为多态?

    多种形态,多种状态,编译和运行有两个不同的状态。
    编译期叫做静态绑定。
    运行期叫做动态绑定。

    class Animal {
    	public void move(){}
    }
    class Cat extends Animal {
    }
    Animal a = new Cat();
    a.move();
    

    编译时,编译器发现a的类型时Animal,所以编译器会去Animal类中找move()方法,找到了,静态绑定,编译通过(这也就是为什么如果访问子类特有的方法时会报错,因为静态绑定出错)
    运行的时候和底层堆内存当中的实际对象有关,真正执行时会自动调用"堆内存中真实对象"的相关方法,也就是会调用Cat类中的move()方法

  2. 向上转型指什么?

    把子类型对象直接赋给父类型引用,如第一条中所演示的:

    Animal a = new Cat();
    
  3. 向上转型发生的时机?

    1. 直接赋值(同2)

    2. 方法传参

      public static void doSome(Animal animal){
      }
      Animal.doSome(new Cat())
      
    3. 方法的返回值

      public static Animal func() {
      	return new Cat();
      }
      
  4. 向下转型指什么?

    通过父类引用调用方法或成员变量时,只能调用父类中已有的方法和字段,要想访问子类中特有的方法和字段,只能向下转型

    class A {
        public void doSome(){}
    }
    class B extends A{
        //子类继承了父类的doSome()
        public void doOther(){}//子类特有的方法
    }
    public static void main(String[] args) {
        A a = new B();
        a.doSome();//  √
        a.doOther();//Cannot resolve method 'doOther' in 'A'
        //这时候只能向下转型
        B b = (B)a;
        b.doOther();//	√
    }
    

    向下转型注意什么?

    最好使用instanceof判断一些,以防出现ClassCastException

    上面代码合适的做法是:

    if(a instanceof B) {
    	B b = (B)a;
    }
    //"如果a这个引用指向的对象时B类型,就向下转型,否则不执行"
    
  5. 重写(override,方法覆盖)

    a、怎么在代码级别上构成方法覆盖?

    • 两个类要有继承关系
    • 重写之后的方法和之前的方法具有相同的返回值类型、方法名、形式参数列表

    b、注意事项?

    • 访问权限不能更低,可以更高
    • 不能被final修饰,被final修饰的方法是密封方法,不能被重写
    • 重写之后的方法不能比之前的方法抛出更多的异常
    • 父类不能被private修饰
    • 方法不能是static修饰的
  6. 和重载(overload)的区别?

    a、重载条件?

    • 在同一个类中,方法名相同,参数列表不同

    • 参数列表不同指

      参数个数不同

      参数顺序不同

      参数类型不同

    • 对返回值类型和修饰符列表无要求

    • 注意:重载不是只能发生在同一个类中

      lf two methods of a lass (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the samename but signatures that are not override-equivalent, then the method name is said to be overloaded. --The Java® Language Specification

      如果一个类的两个方法(无论是在同一个类中声明的,还是由一个类继承的,还是一个声明后继承的)具有相同的名称,但不具有覆盖等效的sianatures,则该方法名被称为重载。

      从Oracle官方文档可以看出,在一个子类中也是可以发生重载的:只要具有相同的方法名,但又不构成覆盖,就是重载。

    b、我们可以用一张图来区分重载和重写的区别:
    重载和重写,【图片来源于网络,侵权必删】

    重写是因为父类的方法不满足子类的业务需求,在父类的基础上进行扩写,而重载是一类功能相似的方法,为了方便代码编写而把方法名定为相同

  7. 构造方法中也能发生动态绑定

    class A {
        public A() {
            func();
        }
        public void func() {
            System.out.println("A的func");
        }
    }
    class B extends A {
        int num = 10;
        @Override
        public void func() {
            //super();隐式调用
            System.out.println("B的func " + num);
        }
    }
    public class Test() {
        public static void main(String[] args) {
            A a = new B();
        }
    }
    //结果: B的func 0
    

    构造 B 对象的时候, 会先调用 A 的构造方法.A的构造方法调用了func方法,此时会触发动态绑定,执行堆内存中"真实对象"的func方法,也就是B类中重写的func方法。此时B对象还未完成构造,故num处在未初始化状态,值为0,故最终输出结果是:“B的func 0”

4、抽象类

  1. 抽象方法没有方法体

    问:没有方法体的方法都是抽象方法?

    错;native方法也没有方法体

    public native int hashCode();
    这个方法底层调用了C++写的动态链接库程序。前面修饰符列表中没有:abstract。有一个native。表示调用JVM本地程序。

  2. 抽象类中可以包含其他的非抽象方法(成员方法和类方法都可),也可以包含字段(静态或实例变量). 非抽象方法可以被重写,也可以被子类直接调用

  3. 抽象类不能实例化

    问:抽象类不能实例化,为什么要包含非抽象方法和构造方法?

    ​ 是用来给子类使用的

  4. 一个非抽象类继承了抽象类,那么这个类必须重写所有的抽象方法

  5. abstract和final是对立的

    因为abstract修饰的类或方法就是为了继承和重写,而final修饰的类不能被继承,修饰的方法不能被重写

  6. 抽象类B可以继承抽象类A,当非抽象类C继承A类时,必须重写A和B类中所有的抽象方法

  7. 抽象方法不能被private修饰,且不能出现在非抽象类中

    abstract private void draw();
    // 编译出错
    //Error:(4, 27) java: 非法的修饰符组合: abstract和private
    
  8. 抽象类也能发生向上、向下转型,即满足多态

5、接口

  1. 概念

    Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)

    在我看来,接口就是一种特殊的类,相比于抽象类中还可以包含非抽象方法,字段,在接口中只能包含静态常量和抽象方法(JDK7以前)

  2. 接口中的方法默认被 public abstract修饰,因此可以省略

  3. 接口中的字段默认被 public static final修饰,也可以省略

  4. 阿里编码规范中约定, 接口中的方法和属性不要加任何修饰符号, 保持代码的简洁性,如下:

    public abstract void doSome();void doSome();
    public static final String NATION=“China”;String NATION=“China”;
    完整格式简化格式(推荐)
  5. 在JDK8以后,接口中可以定义普通方法,但要被"default"修饰,称为默认方法,可以被重写

  6. 各个版本对比

    版本内容
    JDK 7及以前成员常量、抽象方法
    JDK 8默认方法、静态方法
    JDK 9及以后私有方法

    注意:"内容"指新增加的,新版本包含以前版本的内容

  7. 接口不能实例化

  8. 实现多个接口和继承类在代码层次怎么写?

    public class Test extends A implements B, c {
    }
    
  9. 接口中的静态方法不能被实现类使用,也不能被实现类的实例对象调用,只能用Interface.方法名()。相比之下,

    普通类继承父类,可以用子类类名和子类实例对象调用父类中的静态方法,只不过后者不建议使用

  10. 接口和接口之间的关系

    接口和接口之间是继承,实现了接口扩展其他接口的功能
    在这里插入图片描述
    在这里插入图片描述

    可以看到,在java源码中,两个接口之间使用的是"extends"关键字进行维护的

  11. 接口也能发生向上、向下转型,即接口也支持多态

  12. 接口一般以大写 "I"开头,如 " IFly "

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值