Java题集练习3
1 什么时候用instanceof
instanceOf关键字主要用于判断一个对象是否为某个类的子类或是接口的实例,通常用于类型转换和运行时类型判断的场景,比如继承和多态中。比如,创建一个Animal类及其子类Cat和Cat子类Hat,可以使用instanceOf判断:
java
public static void main(String[] args) {
Cat cat = new Cat();
Hat hat = new Hat();
boolean b1 = hat instanceof Animal;
System.out.println(b1);
//true
boolean b2 = cat instanceof Animal;
System.out.println(b2);
//true
boolean b3 = cat instanceof Hat;
System.out.println(b3);
//false
}
b1判断的是Hat类对象是否是Animal的子类,由于Hat是Cat的子类,Cat是Animal类的子类,所以Hat是Animal的子类
b2不难看出,Cat类是Animal类的直属子类
由于Cat是Hat的父类,所以它不属于Hat类的子类,由此得到b3的结果
2 动态绑定和静态绑定
首先,我们要对程序绑定有一个初步的概念:
绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来。对java来说,绑定分为静态绑定和动态绑定;或者叫做前期绑定和后期绑定.
静态绑定:
在程序执行前方法已经被绑定(也就是说在编译过程中就已经知道这个方法到底是哪个类中的方法),此时由 编译器或其它连接程序实现。例如:Java。
针对java简单的可以理解为程序编译期的绑定;这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定
动态绑定:
后期绑定: 在运行时根据具体对象的类型进行绑定。
若一种语言实现了后期绑定,同时必须提供一些机制,可在运行期间判断对象的类型,并分别调用适当的方法。也就是说, 编译器此时依然不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。不同的语言对后期绑定的实现方法是有所区别的。但我们至少可以这样认为:它们都要在对象中安插某些特殊类型的信息。
动态绑定的过程:
-
虚拟机提取对象的实际类型的方法表;
-
虚拟机搜索方法签名;
-
调用方法。
为什么说java中final,static,private和构造方法是前期绑定呢?
我们知道,final修饰的类不能被继承,static修饰的方法不可以被子类重写,但可以被子类隐藏,也就是说,如果子类中重写了static方法,则会调用子类的方法,如果没有重写,则会调用父类中的方法;唯一的不同点就是,如果子类向上转型为父类的对象时,无论子类中是否定义了这个static方法,都会去调用父类中的static方法,所以说static方法是可以被隐藏而不是被覆盖;而private修饰的属性都不能被继承,构造方法也同样是不能被继承的,虽然子类通过super()调用父类的构造方法,但是在重写父类的其他方法时是不用这样做的,所以编译时自然会知道这个构造方法属于哪个类。
3 多态内存
在Java中,多态是面向对象编程的一个重要特性,它允许子类对象被当作父类对象来使用。多态的实现涉及到方法的重写和动态绑定(详见静态绑定和动态绑定)。理解多态的内存模型有助于更好地掌握Java的内部工作机制。
针对对象的内存分配,有以下两个概念:
-
在创建对象时,实际创建的对象被分配在堆内存中
-
创建对象实例的引用被分配在栈内存中
4 为什么要有多态,多态解决了什么问题
我们知道,多态是一种抽象的行为,它允许程序员面向抽象变成而不是面对具体的实现类编程,他可以增强代码的扩展性
例如,小明很喜欢吃苹果,但我们既可以说他喜欢吃苹果,也可以说他喜欢吃水果;如果他某天突然开始变得喜欢吃香蕉,如果说的是他喜欢吃水果就不需要修改;但如果是喜欢吃苹果就需要改成喜欢吃香蕉;这展现了多态的灵活性。
再比如,我想定义一个Person类内有一个方法work()打印"工作",他的子类就可以重写这个work()方法让他打印"上学",这样一来,就可以在创建的对象都是Person类的时候,通过new不同的实现类来体现不同的工作情况,这就是多态。
5 接口和抽象类的异同
相同点:
-
都不能被实例化(创建对象)
-
他们的子类必须实现他们类中所有的抽象方法,才可以被实例化,否则子类仍然为抽象类
不同点:
- 关键字不同:
- 抽象类子类使用继承extends关键字来继承抽象类
- 接口实现类使用关键字implements实现接口
- 抽象类中可以有构造方法,而接口中不允许有构造方法
- 抽象类中既可以有普通方法也可以有抽象方法,接口中只能有抽象方法
- 方法的权限修饰符不同:
- 抽象方法可以用除了private以外的修饰符
- 接口中的方法只能用public修饰
- 抽象类中定义的变量可以是普通变量,接口中只能定义静态的常量
- 抽象类可以继承单个类和实现多个接口,而接口可以实现多继承接口
- 速度:抽象类的速度要比接口快,接口需要时间寻找在类中实现的方法
注意:
1.如果一个类里存在抽象方法,那么他一定是抽象类
2.抽象方法要被实现,不能是静态的,也不可以是私有的
3.接口内含有未被实现的方法,也叫抽象方法,但未使用abstract关键字
6 什么时候使用接口,什么时候使用抽象类
接口的使用场合
-
类之间需要特定接口协调,不在乎其如何实现
-
可以作为实现特定功能的标识存在,也可以作为无接口方法的标识
-
用来将一组类视为单一的类,调用者只能通过接口来访问这些类
-
需要实现特定的多项功能,这些功能间也许毫无联系
抽象类的使用场合
如果既需要统一的接口,还需要实例变量或缺省方法的情况下,可以使用抽象类
7 什么是面向接口编程
面向接口编程,就是在不使用继承的情况下,只使用接口的实现类来处理所需要的问题的逻辑,当需求变化时,只需要编写该需求的实现类即可处理需求,不需要改写大量的代码,减少对系统的影响
8 关键字:4种权限修饰符,static,abstract ,final能否修饰的内容:类,属性,方法,构造方法(表格形式呈现)
类 | 属性 | 方法 | 构造方法 | |
---|---|---|---|---|
4种权限修饰符 | 否 | 能 | 能 | 能 |
static | 否 | 能 | 能 | 否 |
abstract | 能 | 否 | 能 | 否 |
final | 能 | 能 | 能 | 否 |