Java 基础考核
Posted Al_tair
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 基础考核相关的知识,希望对你有一定的参考价值。
Java 基础考核
大家好呀,我是小笙!
基础考核篇
1.抽象类、接口、普通类的区别?
我们以普通类为基准点来进行比较分析他们之间的关系
抽象类和类的区别:
1.不能被实例化(思考:那为什么要构造器?)
说明:抽象类的构造器不是用于抽象类本身,更多是为了在调用子类的构造器的时候,调用父类的构造器进行参数的初始化
2.抽象类可以使用抽象方法,但是普通类不行
// 抽象类组成
public abstract class AbstractClassExample
// 属性
private int y;
// 静态属性
public static int x;
// 构造器:可以被子类用super关键字调用构造器
public AbstractClassExample()
// 代码块
// 抽象方法:不能使用private,final和static修饰符,因为这些修饰符都是和重写相违背的
// 访问修饰符 abstract 返回类型 方法名(参数列表); // 没有方法体
public abstract void func1();
// 普通方法
public void func2()
System.out.println("func2");
// 静态方法
public static void func3()
System.out.println("func3");
接口和普通类的区别:
1.不能被实例化
2.改变了类的特性:可以实现接口之间的多继承,类与接口之间的多实现
// 接口组成
// 访问修饰符 interface 接口名 访问修饰符:public 和默认
interface Interface
// 静态属性 默认是public static final修饰
// 可以通过 接口名.属性名来访问属性
int n1 = 10;
// 静态内部类 默认是public static final修饰,可以实现当前接口
class InterfaceInnerClass;
// 静态方法 默认是public修饰
static void method3()
System.out.println("静态方法");
// 抽象方法 默认是public abstract
void method1();
// 在jdk1.8之后,出现默认方法 添加default关键字 默认是public
default public void method2()
System.out.println("默认方法");
抽象类 Vs 接口
- 从设计层面上看,抽象类提供了一种 IS-A 关系,那么就必须满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求接口和实现接口的类具有 IS-A 关系
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口
- 接口的成员只能是 public 修饰的,而抽象类的成员可以有多种访问修饰符
- 抽象可以有普通方法(含有方法体),接口只能是默认方法(带有default关键字)
使用选择
使用接口:
- 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Compareable 接口中的 compareTo() 方法
- 需要使用多重继承(通过多个接口实现弥补单继承)
使用抽象类:
-
需要在几个相关的类中共享代码
-
需要能控制继承来的成员的访问权限,而不是都为 public
常见面试题
1.接口中可以有构造函数嘛?
构造函数的核心用处:创建对象和初始化参数
接口不能被实例化,接口参数都是静态常量,不需要初始化参数,因此不需要构造器
2.谈谈对接口编程的理解
接口我们可以理解为定义某种规范,就是比如 mysql 数据库想要Java去操作,必须实现Java给出的规范,也就是驱动;接口编程时功能编程,能够很好的降低程序的解耦
2.异常机制如何实现?
异常是什么?
异常就是程序代码出现了问题,但是非致命问题(错误 error 就是致命问题,程序必须结束:栈溢出等),我们需要去处理这些异常;异常机制就是发现异常,封装异常,处理异常的一种机制
为什么需要发现异常?
异常的精准定位能够更加高效地发现问题然后解决问题
异常体系图
异常类的种类
编译时异常:在代码编译前就出现的异常必须解决之后才可以运行
运行时异常:代码被加载到虚拟机中运行时候出现的异常
注意:需要记住几个异常类的例子,编译时异常往往时找不到,运行时异常往往时逻辑上的错误
异常的处理
- try – 用于监听。将要被监听的代码(可能抛出异常的代码)放在try语句块之内,当try语句块内发生异常时,异常就被抛出。
- catch – 用于捕获异常。catch用来捕获try语句块中发生的异常。
- finally – finally语句块总是会被执行。它主要用于回收在try块里打开的资源(如数据库连接、网络连接和磁盘文件)。只有finally块,执行完成之后,才会回来执行try或者catch块中的return或者throw语句,如果finally中使用了return或者throw等终止方法的语句,则就不会跳回执行,直接停止。
- throw – 用于抛出异常。
- throws – 用在方法签名中,用于声明该方法可能抛出的异常。
public void exceptionClass throws Exception // 方法无法捕获异常,向调用者抛出异常
// try - catch - finally格式如下
try
// 代码可能有异常
// 如果没有出现异常,则执行try块中所有的语句,反之有出现异常,则不再执行try块中剩余的语句,抛出异常
catch(NullPointerException e)
// 捕获异常
// 1.当异常发生时,才会执行catch内的代码
// 2.系统将异常封装成Exception对象e,传递给catch
// 3.同一个 catch 也可以捕获多种类型异常,用 | 隔开
catch(RuntimeException e)
// 可以有多个catch语句进行捕获不同的异常,要求子类异常在父类异常之前,不然就没有子类异常存在的意义
throw new RuntimeException("运行时异常"); // 在方法内无法解决,可以抛出运行时异常
finally
// 不管是否有异常,一般都会执行
// 总结:finally遇见如下情况不会执行
// 1.在前面的代码中用了System.exit()退出程序。
// 2.finally语句块中发生了异常。
// 3.程序所在的线程死亡。
// 4.关闭CPU。
补充:throw或者throws 抛出形式
常见面试题
1.请说明JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
Java 通过面向对象的方法进行异常处理,把各种不同的异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,它是Throwable类或其它子类的实例。当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息,调用这个对象的方法可以捕获到这个异常并进行处理。
Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally。一般情况下是用try来执行一段程序,如果出现异常,系统会抛出(throws)一个异常,这时候你可以通过它的类型来捕捉(catch)它,或最后(finally)由缺省处理器来处理。用try来指定一块预防所有”异常”的程序。紧跟在try程序后面,应包含一个catch子句来指定你想要捕捉的”异常”的类型。throw语句用来明确地抛出一个”异常”。throws用来标明一个成员函数可能抛出的各种”异常”。Finally为确保一段代码不管发生什么”异常”都被执行一段代码。可以在一个成员函数调用的外面写一个try语句,在这个成员函数内部写另一个try语句保护其他代码。每当遇到一个try语句,”异常“的框架就放到堆栈上面,直到所有的try语句都完成。如果下一级的try语句没有对某种”异常”进行处理,堆栈就会展开,直到遇到有处理这种”异常”的try语句。
3.对泛型的理解
泛型:字面上的意思就是广泛的类型,传入类型是不确定的,只有在编译之后才会被确认
泛型特点:
1.可以使用任意字母A-Z,用作占位符,表示传入的类型(可以用于属性类型,方法参数传入类型,方法返回类型)
2.只能指代引用类型的数据(因为在编译之前需要进行类型擦除,裸类型为 Object 类型(准确的来说是替换成它们非泛型上界),但是基本数据类型不能和 Object 类型进行转换)
3.指定传入类型,但是可以真实传入该类型的子类型,类似于向上转型的用法
// 自定义泛型
class Template<E>
E filed;
// 方法返回
public E method()
return filed;
// 方法传入
public Template(E filed)
this.filed = filed;
泛型擦除的原理:
java里面的泛型只存在于源代码里面,一旦经过编译之后,所有的泛型都会被擦除掉,全部被替换为原来的裸类型 Object 类型,并在对元素进行访问和修改的时候,才会加上强制类型转换
类型擦除的优点
实现简单,运行期也能够节省一些类型所占的内存空间
类型擦除的缺点
1.使用类型擦除直接导致了对于原始的数据类型无法支持,比如int,long这种,因为java不支持Object类型和基本数据类型之间的强制类型转换,也就是说一旦类型擦除之后,就没法在进行 类型转换了。也正是这样,现在的泛型都是不支持原始类型的,比如ArrayList< Integer >,而不能使用ArrayList< int >
2.运行期间无法获得泛型类型信息。因为泛型都被擦除了,都被替换成了裸类型。这样就导致了下面的程序都会报错,比如无法使用泛型来创建对象,或者数组
常见面试题
1.在开发中使用泛型取代非泛型的数据类型(比如用ArrayList取代ArrayList),程序的运行时性能会变得更好(错误)
解析:泛型仅仅是 java 的语法糖,它不会影响 java 虚拟机生成的汇编代码,在编译阶段,虚拟机就会把泛型的类型擦除,还原成没有泛型的代码,顶多编译速度稍微慢一些,执行速度是完全没有什么区别的
2.什么是泛型?泛型的作用?
- Java 泛型(Generics)是 JDK 5 中引入的一个新特性。
- 使用泛型参数,可以增强代码的可读性以及稳定性。编译器可以对泛型参数进行检测,并且通过泛型参数可以指定传入的对象类型。比如
ArrayList<Persion> persons = new ArrayList<String>()
这行代码就指明了该ArrayList
对象只能传入Persion
对象,如果传入其他类型的对象就会报错。 - 可以用于构建泛型集合。原生
List
返回类型是Object
,需要手动转换类型才能使用,使用泛型后编译器自动转换。
以上是关于Java 基础考核的主要内容,如果未能解决你的问题,请参考以下文章