title: java基础之面向对象(三大特征:封装性,继承性、多态)
date: 2020-09-23 21:31:03
tags:
一、多态:
1、理解:一个事物可以有多种形态,例如人,分为男人,女人。 男人,女人都继承了人这个特性。
2、使用的总结:(适用前提:继承关系,重写方法)
2.1:编译看左边;运行看右边。编译期时,只能调用父类的已有方法,但是实际在运行时,运行的是我们重写的父类的方法。
2.2:对象的多态只用于方法,不能用于属性。
2.3:想用子类的属性和方法时,使用向下转型。因为我们声明的时候是把子类转换成父类,所以我们只能用父类已有的,但是内存中实际已经加载了子类特有的方法和属性。只要我们通过强制转换成原来的类型即可。
Person p = new man();//这里只能用父类的属性、方法,父类是抽象类也可以这样,然后调用父类抽象方法也可以运行,调用的是子类重写的方法。
man m = (man)p;//向下转型,可以用子类方法
2.3.1: ClassCastException的异常,如果我们向下转型的时候,之前声明的子类是man(),但是向下转型时我们转成women(),这是不被允许的,要求向下转型的类型是之前那个类(必须是之前的这个类,这个类的子类也不行)。
多态的面试题:
3.1 谈谈你对多态性的理解?
① 实现代码的通用性。
② Object类中定义的public boolean equals(Object obj){ }
JDBC:使用java程序操作(获取数据库连接、CRUD)数据库(MySQL、Oracle、DB2、SQL Server)
③ 抽象类、接口的使用肯定体现了多态性。(抽象类、接口不能实例化)
3.2 多态是编译时行为还是运行时行为?
运行时行为。证明:利用随机数产生不同的对象(这几个类继承同一个父类),每次随机出来的对象是不一样的,说明运行时才会得到具体是哪个对象。
二、static关键字(静态的)
static是与类绑定的,早于对象创建。
1、通常修饰的结构:属性、方法、代码块、内部类
2、修饰属性时(静态变量)
当我们创建多个同一个类的对象时,多个对象共享一个static变量,如果其中一个对象修改这个static变量,其他对象所获得的值也会改变。
其他说明:
2.1 静态变量随着类的加载。可以通过“类.静态变量”的方法进行调用。
2.2 类只会加载一次,所以静态变量也只会存在一份,存在方法区的静态域中。(方法区包括:类的加载信息,静态域、常量池)
3、static修饰方法
1 随着类的加载而加载,调用方法:“类.静态方法”的方式调用,不需要创建对象
2 静态方法只能调用静态的。非静态方法既可以调用静态的,也可以调用非静态的。
三、代码块(一般用于初始化类、对象的信息)
1 静态代码块(static修饰)
>内部可以输出语句。
>
>随着类的加载而加载,只能执行一次,用于初始化类的信息。
>
>如果一个类定义了多个静态代码块,则按照声明的先后顺序执行。
>
>静态只能调用静态。
2 非静态代码块
内部可以输出语句。
随着对象的创建而创建,每创建一个对象就执行一次非静态代码块,可以对对象的属性进行初始化
如果一个类定义了多个非静态代码块,则按照声明的先后顺序执行。
非静态可以调用静态和非静态。
四、abstract关键字(抽象的,修饰类,方法)
1、修饰类
>此类不能被实例化,必须要有构造器,以供于子类实例化
>
>一般都会有子类去继承一个抽象类,让子类对象实例化去操作
2、修饰方法
>> 如果修饰方法,只是声明了这个方法,不能有方法体
>
>> 如果子类重写了父类的所有抽象方法,此子类可以实例化,没有重写所有不可以实例化
3、注意点
包含抽象方法的类一定是抽象类,但是抽象类不一定所有都是抽象方法,可以没有抽象方法。
五、内部类
1、分类:成员内部类(静态、非静态),局部内部类(方法内、代码块内、构造器内)
2、成员内部类:
2.1 作为外部类的成员
可以调用外部类的结构
可以被static修饰
可以被4中不同的权限修饰符修饰
2.2 作为一个类
可以定义属性、方法、构造器等
可以被继承,final,abstract修饰
2.3 创建成员内部类的对象(静态的、非静态的)
创建静态的Dog内部类的实例(静态的成员内部类)
Person.Dog dog = new Person.Dog();
创建非静态的的成员内部类
Person p = new Person();
Person.Bird brid = p.new Bird();
2.4 调用外部类的结构
class Person{
String name = "小明";
public void eat(){
}
//非静态成员内部类
class Bird{
String name = "杜鹃";
public void display(String name){
System.out.println(name);//方法的形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
//Person.this.eat();
}
}
}
3、局部内部类
局部内部类的使用(通常用匿名内部类,即为方式二)
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable(){
//创建一个实现了Comparable接口的类:局部内部类
//方式一:
// class MyComparable implements Comparable{
//
// @Override
// public int compareTo(Object o) {
// return 0;
// }
//
// }
//
// return new MyComparable();
//方式二:
return new Comparable(){
@Override
public int compareTo(Object o) {
return 0;
}
};
}
**注意点:在一个方法中有局部变量是,也有局部内部类,如果这个局部内部类想用方法中的局部变量,可以直接用(其实这个变量是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):和上面一样,还多了一个其他线程可以中断当前线程