title: java基础之面向对象(三大特征:封装性,继承性、多态)
date: 2020-09-23 21:31:03
tags:

一、多态:

  1. 1、理解:一个事物可以有多种形态,例如人,分为男人,女人。 男人,女人都继承了人这个特性。
  2. 2、使用的总结:(适用前提:继承关系,重写方法)
  3. 2.1:编译看左边;运行看右边。编译期时,只能调用父类的已有方法,但是实际在运行时,运行的是我们重写的父类的方法。
  4. 2.2:对象的多态只用于方法,不能用于属性。
  5. 2.3:想用子类的属性和方法时,使用向下转型。因为我们声明的时候是把子类转换成父类,所以我们只能用父类已有的,但是内存中实际已经加载了子类特有的方法和属性。只要我们通过强制转换成原来的类型即可。
  1. Person p = new man();//这里只能用父类的属性、方法,父类是抽象类也可以这样,然后调用父类抽象方法也可以运行,调用的是子类重写的方法。
  2. man m = (man)p;//向下转型,可以用子类方法
  1. 2.3.1: ClassCastException的异常,如果我们向下转型的时候,之前声明的子类是man(),但是向下转型时我们转成women(),这是不被允许的,要求向下转型的类型是之前那个类(必须是之前的这个类,这个类的子类也不行)。

多态的面试题:

3.1 谈谈你对多态性的理解?
① 实现代码的通用性。
② Object类中定义的public boolean equals(Object obj){ }
JDBC:使用java程序操作(获取数据库连接、CRUD)数据库(MySQL、Oracle、DB2、SQL Server)
③ 抽象类、接口的使用肯定体现了多态性。(抽象类、接口不能实例化)
3.2 多态是编译时行为还是运行时行为?

  1. 运行时行为。证明:利用随机数产生不同的对象(这几个类继承同一个父类),每次随机出来的对象是不一样的,说明运行时才会得到具体是哪个对象。

二、static关键字(静态的)

  1. static是与类绑定的,早于对象创建。

1、通常修饰的结构:属性、方法、代码块、内部类

2、修饰属性时(静态变量)

  1. 当我们创建多个同一个类的对象时,多个对象共享一个static变量,如果其中一个对象修改这个static变量,其他对象所获得的值也会改变。
  2. 其他说明:
  3. 2.1 静态变量随着类的加载。可以通过“类.静态变量”的方法进行调用。
  4. 2.2 类只会加载一次,所以静态变量也只会存在一份,存在方法区的静态域中。(方法区包括:类的加载信息,静态域、常量池)

3、static修饰方法

  1. 1 随着类的加载而加载,调用方法:“类.静态方法”的方式调用,不需要创建对象
  2. 2 静态方法只能调用静态的。非静态方法既可以调用静态的,也可以调用非静态的。

三、代码块(一般用于初始化类、对象的信息)

  1. 1 静态代码块(static修饰)
  1. >内部可以输出语句。
  2. >
  3. >随着类的加载而加载,只能执行一次,用于初始化类的信息。
  4. >
  5. >如果一个类定义了多个静态代码块,则按照声明的先后顺序执行。
  6. >
  7. >静态只能调用静态。
  1. 2 非静态代码块

内部可以输出语句。

随着对象的创建而创建,每创建一个对象就执行一次非静态代码块,可以对对象的属性进行初始化

如果一个类定义了多个非静态代码块,则按照声明的先后顺序执行。

非静态可以调用静态和非静态。

四、abstract关键字(抽象的,修饰类,方法)

  1. 1、修饰类
  1. >此类不能被实例化,必须要有构造器,以供于子类实例化
  2. >
  3. >一般都会有子类去继承一个抽象类,让子类对象实例化去操作
  1. 2、修饰方法
  1. >> 如果修饰方法,只是声明了这个方法,不能有方法体
  2. >
  3. >> 如果子类重写了父类的所有抽象方法,此子类可以实例化,没有重写所有不可以实例化
  1. 3、注意点

包含抽象方法的类一定是抽象类,但是抽象类不一定所有都是抽象方法,可以没有抽象方法。

五、内部类

1、分类:成员内部类(静态、非静态),局部内部类(方法内、代码块内、构造器内)

2、成员内部类:

2.1 作为外部类的成员

可以调用外部类的结构

可以被static修饰

可以被4中不同的权限修饰符修饰

2.2 作为一个类

可以定义属性、方法、构造器等

可以被继承,final,abstract修饰

2.3 创建成员内部类的对象(静态的、非静态的)

创建静态的Dog内部类的实例(静态的成员内部类)

  1. Person.Dog dog = new Person.Dog();

创建非静态的的成员内部类

  1. Person p = new Person();
  2. Person.Bird brid = p.new Bird();

2.4 调用外部类的结构
  1. class Person{
  2. String name = "小明";
  3. public void eat(){
  4. }
  5. //非静态成员内部类
  6. class Bird{
  7. String name = "杜鹃";
  8. public void display(String name){
  9. System.out.println(name);//方法的形参
  10. System.out.println(this.name);//内部类的属性
  11. System.out.println(Person.this.name);//外部类的属性
  12. //Person.this.eat();
  13. }
  14. }
  15. }

3、局部内部类

局部内部类的使用(通常用匿名内部类,即为方式二)

  1. //返回一个实现了Comparable接口的类的对象
  2. public Comparable getComparable(){
  3. //创建一个实现了Comparable接口的类:局部内部类
  4. //方式一:
  5. // class MyComparable implements Comparable{
  6. //
  7. // @Override
  8. // public int compareTo(Object o) {
  9. // return 0;
  10. // }
  11. //
  12. // }
  13. //
  14. // return new MyComparable();
  15. //方式二:
  16. return new Comparable(){
  17. @Override
  18. public int compareTo(Object o) {
  19. return 0;
  20. }
  21. };
  22. }
  1. **注意点:在一个方法中有局部变量是,也有局部内部类,如果这个局部内部类想用方法中的局部变量,可以直接用(其实这个变量是final的,jdk8及以后省略了,以前的必须要显示声明)。**

面试题

解释一下HashCode()和equals()的联系

1、 相同的对象要有相同的hashcode
2、如果两个对象hashcode相同不一定相同

说明重载和重写的区别,重载方法能不能根据返回类型区分

二者都是实现多态的方式,重载是编译是的多态,重写是运行时的多态。
重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同,参数个数不同或者二者都不同)就是重载。
重写发生在子父类中,重写要求子类重写的方法和父类方法要用相同的返回类型,并且访问权限要大于被重写方法。
重载对返回值类型没有要求

内部类可以引用外部类的成员吗,有什么限制

如果内部类不是static那么他可以访问创建尾部类的所有属性,如果是static那只能访问static属性。
一般普通类只有public或package的访问修饰,而内部类可以实现static protected private等访问修饰。
当外部类继承的时候内部类是不会被覆盖的,如果内部类中有明确的继承,就可以覆盖原来内部类的方法。

接口和抽象类的区别是什么

1、 接口的方法默认是publilc,所有方法在接口中不能有实现(java8开始可以有默认实现),抽象类可以有非抽象的方法。
2、 接口中实例变量默认是final类型,而抽象类不一定
3 、 一个类可以实现多个接口,但只能继承一个抽象类
4、 接口是对行为的规范,抽象类是对类的抽象。

说明一下final,finally,finalize的区别

final用于声明属性,方法和类,分别标识属性不可变,方法不可覆盖,类不可继承
finally是异常处理语句结构的一部分,表示总是执行
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾 收集时的其他资源回收,例如关闭文件等。

说明Comparable和Comparator接口的作用以及区别

Comparable接口只包含一个compareTo()方法,这个方法可以给两个对象排序。具体来说,它返回附属,0,正数就表示比传进来的小,相等,大于。
Comparator接口包含compare()和equals()两个方法,compare()方法返回-1,0,1表示第一参数小于,等于,大于第二个参数。equals()方法需要一个对象作为参数,她用来决定输入参数是否和comparator相等。只有当输入参数也是一个comparator和当前comparator的排序结果是一样的,这个方法才返回true。

请列举你所知道的object的方法并简要说明

Object():默认构造方法
clone():创建并返回此对象的一个副本
finalize():当垃圾回收器确定不存在该对象的更多引用的时候,由对象的垃圾回收器调用此方法。
getClass():返回一个对象的运行时类。
hashCode():返回该对象的哈希码
notify():唤醒在此对象监视器上等待的单个线程。
nontifyAll():唤醒在此对象监视器上等待的所有线程。
toString():返回该对象的字符串表示
wait():导致当前线程等待,直到其他线程调用此对象的notify()或者notifyAll()。
wait(long timeout):和上面一样,额外或者超过了指定时间量
wait(long timeout,int nanos):和上面一样,还多了一个其他线程可以中断当前线程