面试总结——Java基础
1.为什么内部类访问的外部变量需要使用final修饰 ?
因为生命周期的原因。方法中的局部变量,方法结束后这个变量就要释放掉,final保证这个变量始终指向一个对象。
首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁。问题就来了,如果外部类的方法中的变量不定义final,那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量 所指向的内存区域就不会变。
2.Java异常
异常是指程序运行时(非编译)所发生的非正常情况或错误,当程序违反了语音规则,jvm就会将出现的错误表示一个异常抛出。 异常也是java 的对象,定义了基类 java.lang.throwable作为异常父类。 这些异常类又包括error和exception两大类 。
error类异常主要是运行时逻辑错误导致,一个正确程序中是不应该出现error的,当出现error一般jvm会终止。 不建议去捕获。
exception表示可恢复异常,包括检查异常和运行时异常。
检查异常是最常见异常比如 io异常sql异常,都发生在编译阶段,这类通过try、catch捕捉 。
运行时异常,编译器没有强制对其进行捕捉和处理,一般都会把异常向上抛出,直到遇到处理代码位置,若没有处理块就会抛到最上层,多线程用thread.run()抛出,单线程用main()抛出。
3.Java语言中的异常处理包括声明异常、抛出异常、捕获异常和处理异常四个环节。
throw用于抛出异常。throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异常对象。
try是用于检测被包住的语句块是否出现异常,如果有异常,则抛出异常,并执行catch语句。
cacth用于捕获从try中抛出的异常并作出处理。
finally语句块是不管有没有出现异常都要执行的内容。
4.Java常用工具
Javaprof.exe :Java剖析工具;
jdb.exe:Java调试器;
javadoc.exe:JDK中提供的文档生成器
Javac.exe :Java编译器,将java源文件编译成字节码文件
Java.exe:Java解释器
5.static关键字作用?
第一,为某特定数据类型或对象分配单一的存储空间,与创建对象的个数无关;第二,实现某个方法或属性与类而不是对象关联在一起,也就是说在不创建对象的情况下就可以通过类来直接调用方法或使用类的属性。
static的四种用法:
(1)static成员变量(静态变量):java没有全局概念,可以通过static修饰达到全局效果。静态变量属于类,其所有实例都指向同一个内存地址,只要它所在的类被加载,这个静态变量就会被分配存储空间。
(2)static成员方法:是类的方法而不是对象的方法,可直接通过类名调用。static方法中不能使用this和super关键字,不能调用非static方法,只能访问所属类的静态成员变量和成员方法。
(3)static代码块(静态代码块):在类中是独立的,不在任何一个方法体内,JVM在加载类时会执行static代码块,static代码块经常被用来初始化静态变量。
(4)static内部类:不依赖于外部类实例对象而被实例化,需要在外部类实例化后才能实例化。不能和外部类有相同的名字,不能访问外部类的普通成员变量,只能访问外部类的静态成员和静态方法。
6.Java程序初始化顺序?
优先级依次递减:(1)静态对象优先于非静态对象(静态对象初始化一次,非静态对象初始化多次);(2)父类优先于子类;(3)按照成员变量定义的顺序。
顺序如下:父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、子类构造函数。
7.抽象类与接口
7.1抽象类通常代表一个抽象概念,他提供一个继承的出发点,当设计一个新的抽象类时,一定是用来继承的。所以,在一个以继承关系形成的等级结构里面,树叶节点应当是具体类,而树枝节点均应当是抽象类。
在使用抽象类时需要注意几点:
(1) 抽象类不能被实例化(像刚才的动物,实例化是没有任何意义的),实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。
(2) 抽象方法必须由子类来进行重写。
(3) 如果类中包含抽象方法,该类必须要定义成抽象类,不管是否还包含有其他方法。
(4) 抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
(5) 子类中的抽象方法不能与父类的抽象方法同名。
(6) abstract不能与final并列修饰同一个类。
(7) bstract 不能与private、static、final或native并列修饰同一个方法。
7.2接口是用来建立类与类之间的协议,它所提供的只是一种形式,而没有具体的实现。同时实现该接口的实现类必须要实现该接口的所有方法. 接口是抽象类的延伸,java了保证数据安全是不能多重继承的,也就是说继承只能存在一个父类,但是接口不同,一个类可以同时实现多个接口,不管这些接口之间有没有关系,所以接口弥补了抽象类不能多重继承的缺陷,但是推荐继承和接口共同使用,因为这样既可以保证数据安全性又可以实现多重继承。
在使用接口过程中需要注意如下几个问题:
(1 )Interface的所有方法访问权限自动被声明为public。
(2) 接口中的“成员变量”会自动变为public static final(不可变的常量)类型。可以通过类命名直接访问:ImplementClass.name。
(3) 接口中不存在实现的方法。
(4) 实现接口的非抽象类必须要实现该接口的所有方法。抽象类可以不用实现。
(5) 不能使用new操作符实例化一个接口,但可以声明一个接口变量,该变量必须引用(refer to)一个实现该接口的类的对象。可以使用 instanceof 检查一个对象是否实现了某个特定的接口。例如:if(anObject instanceof Comparable){}。
(6) 在实现多接口的时候一定要避免方法名的重复。
(7) 一个类可以支持多个接口,多个类也可以支持相同的接口
7.3 抽象类与接口的区别:
7.3.1语法层次
(1) Java接口和Java抽象类最大的一个区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以
(2) 一个抽象类的实现只能由这个抽象类的子类给出,任何一个实现了一个Java接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个Java接口,从而这个类就有了多种类型。
(3) 对子类而言,它只能继承一个抽象类(这是java为了数据安全而考虑的),但是却可以实现多个接口。
7.3.2 设计层次
(1) 抽象层次不同: 抽象类是对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。
(2 ) 设计层次不同: 所以说抽象类是自底向上抽象而来的,接口是自顶向下设计出来的.
(3) 跨域不同: 抽象类所体现的是一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在”is-a” 关系,即父类和派生类在概念本质上应该是相同的。对于接口则不然,并不要求接口的实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已。