类、抽象类、匿名类、内部类、继承、接口、泛型
1.获得一个类的类对象有哪些方式
2.重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
3.说出几条 Java 中方法重载的最佳实践
4.抽象类和接口的区别
5.抽象类中是否可以有静态的main方法
6.抽象类是否可实现(implements)接口
7.抽象类是否可继承具体类(concrete class)
8.匿名内部类是否可以继承其它类?是否可以实现接口
9.内部类分为几种
10.内部类可以引用它的包含类(外部类)的成员吗
11.请说一下 Java 中为什么要引入内部类?还有匿名内部类
12.继承(Inheritance)与聚合(Aggregation)的区别在哪里
13.继承和组合之间有什么不同
14.为什么类只能单继承,接口可以多继承
15.存在两个类,B 继承 A,C 继承 B,能将 B 转换为 C 么?如 C = (C) B
16.如果类 a 继承类 b,实现接口c,而类 b 和接口 c 中定义了同名变量,请问会出现什么问题
17.接口是什么
18.接口是否可继承接口
19.为什么要使用接口而不是直接使用具体类?接口有什么优点
20.泛型的存在是用来解决什么问题
1.获得一个类的类对象有哪些方式
- 方法1:类型.class,例如:String.class
- 方法2:对象.getClass(),例如:"hello".getClass()
- 方法3:Class.forName(),例如:Class.forName("java.lang.String")
2.重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求。
不能,因为调用时不能指定类型信息,编译器不知道你要调用哪个函数。
3.说出几条 Java 中方法重载的最佳实践
下面有几条可以遵循的方法重载的最佳实践来避免造成自动装箱的混乱。
a)不要重载这样的方法:一个方法接收 int 参数,而另个方法接收 Integer 参数。
b)不要重载参数数量一致,而只是参数顺序不同的方法。
c)如果重载的方法参数个数多于 5 个,采用可变参数。
4.抽象类和接口的区别
参数 |
抽象类 |
接口 |
默认的方法实现 |
它可以有默认的方法实现 |
接口完全是抽象的。它根本不存在方法的实现 |
实现 |
子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现。 |
子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现 |
构造器 |
抽象类可以有构造器 |
接口不能有构造器 |
与正常Java类的区别 |
除了你不能实例化抽象类之外,它和普通Java类没有任何区别 |
接口是完全不同的类型 |
访问修饰符 |
抽象方法可以有public、protected和default这些修饰符 |
接口方法默认修饰符是public。你不可以使用其它修饰符。 |
main方法 |
抽象方法可以有main方法并且我们可以运行它 |
接口没有main方法,因此我们不能运行它。 |
多继承 |
抽象方法可以继承一个类和实现多个接口 |
接口只可以继承一个或多个其它接口 |
速度 |
它比接口速度要快 |
接口是稍微有点慢的,因为它需要时间去寻找在类中实现的方法。 |
添加新方法 |
如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 |
如果你往接口中添加方法,那么你必须改变实现该接口的类。 |
5.抽象类中是否可以有静态的main方法
抽象类中可以有静态的main方法,main方法都是
6.抽象类是否可实现(implements)接口
接口可以继承接口。
抽象类可以实现(implements)接口,抽象类可继承实体类,但前提是实体类必须有明确的构造函数。
7.抽象类是否可继承具体类(concrete class)
接口可以继承接
口。抽象类可以实现(implements)接口,
抽象类可继承实体类,但前提是实体类必须有明确的构造函数。
8.匿名内部类是否可以继承其它类?是否可以实现接口
匿名的内部类不能extends(继承)其它类,但一个内部类可以作为一个接口,由另一个内部类实现。
可以实现接口
9.内部类分为几种 参考链接
Java内部类分4中:成员内部类、局部内部类、静态内部类、匿名内部类。
1、成员内部类:即作为外部类的一个成员存在,与外部类的属性、方法并列。
2、局部内部类:即在方法中定义的内部类,与局部变量类似,在局部内部类前不加修饰符public或private,其范围为定义它的代码块。
3、静态内部类:静态内部类定义在类中,任何方法外,用static定义。
4、匿名内部类 :匿名内部类是一种特殊的局部内部类,创建时不需要指定类的名字,但是该类必须要要继承抽象类或者是实现接口。
10.内部类可以引用它的包含类(外部类)的成员吗
一个内部类对象可以访问创建它的外部类对象的成员,包括私有成员。
11.请说一下 Java 中为什么要引入内部类?还有匿名内部类 参考链接
完善多重继承、实现事件驱动系统、闭包。
匿名内部类也就是没有名字的内部类,正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
12.继承(Inheritance)与聚合(Aggregation)的区别在哪里
继承是编译期邦定,聚合和运行期邦定,之所以鼓励聚合不鼓励继承是因为聚合的晚绑定特性,让程序能在运行期改变聚合类变为有可能
13.继承和组合之间有什么不同
1)组合(has-a)关系可以显式地获得被包含类(继承中称为父类)的对象,而继承(is-a)则是隐式地获得父类的对象,被包含类和父类对应,而组合外部类和子类对应。
2)组合关系在运行期决定,而继承关系在编译期就已经决定了。
3)组合是在组合类和被包含类之间的一种松耦合关系,而继承则是父类和子类之间的一种紧耦合关系。
4)当选择使用组合关系时,在组合类中包含了外部类的对象,组合类可以调用外部类必须的方法,而使用继承关系时,父类的所有方法和变量都被子类无条件继承,子类不能选择。
5)最重要的一点,使用继承关系时,可以实现类型的回溯,即用父类变量引用子类对象,这样便可以实现多态,而组合没有这个特性。
6)还有一点需要注意,如果你确定复用另外一个类的方法永远不需要改变时,应该使用组合,因为组合只是简单地复用被包含类的接口,而继承除了复用父类的接口外,它甚至还可以覆盖这些接口,修改父类接口的默认实现,这个特性是组合所不具有的。
7)从逻辑上看,组合最主要地体现的是一种整体和部分的思想,例如在电脑类是由内存类,CPU类,硬盘类等等组成的,而继承则体现的是一种可以回溯的父子关系,子类也是父类的一个对象。
8)这两者的区别主要体现在类的抽象阶段,在分析类之间的关系时就应该确定是采用组合还是采用继承。
9)引用网友的一句很经典的话应该更能让大家分清继承和组合的区别:组合可以被说成“我请了个老头在我家里干活” ,继承则是“我父亲在家里帮我干活"。
14.为什么类只能单继承,接口可以多继承 参考链接
如果存在多继承,那个两个父类有两个一模一样的方法怎么办,子类应该继承哪一个方法。你也许会问如果多个接口中有相同的方法怎么办:接口中的方法都是方法名,没有函数体,具体的实现需要靠实现类去实现,一旦实现类实现了方法,那么就不存在多个接口有相同的方法名的出现的问题了,因为函数体都是一样的。
15.存在两个类,B 继承 A,C 继承 B,能将 B 转换为 C 么?如 C = (C) B
不能,参考里氏替换原则
16.如果类 a 继承类 b,实现接口c,而类 b 和接口 c 中定义了同名变量,请问会出现什么问题
在编译时会发生错误(错误描述不同的JVM有不同的信息,意思就是未明确的x调用,两个x都匹配(就象在同时import java.util和java.sql两个包时直接声明Date一样
17.接口是什么
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。 两种含义:一,Java接口,Java语言中存在的结构,有特定的语法和结构;二,一个类所具有的方法的特征集合,是一种逻辑上的抽象。
18.接口是否可继承接口
接口可以继承接口..但是要使用extends~而不是用implements
19.为什么要使用接口而不是直接使用具体类?接口有什么优点
实现多态……同一个接口,却可以调用不同的底层实现。接口是定义行为,抽象类是实现公共行为的,具体类是实现具体行为的
使用接口其实就有点像实现虚函数的调用一样, 用继承接口的子类实例化声名得接口就可以经过接口调用子类外部接口定义的函数。使用这种接口方式编程, 如果业务逻辑发生变化需求新增类多办法, 就可以再不改动原来已经写好的代码基础上新增一个类来实现接口中定义的函数来实现!
20.泛型的存在是用来解决什么问题 参考链接
泛型的引入可以解决之前的集合类框架在使用过程中通常会出现的运行时刻类型错误,因为编译器可以在编译时刻就发现很多明显的错误。
引入泛型之前,要想实现一个通用的、可以处理不同类型的方法,你需要使用 Object 作为属性和方法参数
Object缺点:
每次使用时都需要强制转换成想要的类型
在编译时编译器并不知道类型转换是否正常,运行时才知道,不安全
泛型的主要目的就是为了创建容器类
泛型的好处:
编译时的强类型检查
消除显示的类型强制转换
更好的代码复用性,比如实现泛型算法