撩课-Java每天10道面试题第4天

撩课Java+系统架构 视频 点击开始学习
31.静态变量和实例变量的区别?
静态变量也叫类变量,
这种变量前加了static修饰符。
可以直接用类名调用,
也可以用对象调用,
而且所有对象的同一个类变量 
都是共享同一块内存空间。

实例变量也叫对象变量,
这种变量没有加static修饰符。
只能通过对象调用, 
而且所有对象的同一个实例变量
是共享不同的内存空间的。

区别在于:
静态变量是所有对象共有的,
某一个对象将它的值改变了,
其他对象再去获取它的值,
得到的是改变后的值;
实例变量则是每一个对象私有的,
某一个对象将它的值改变了,
不影响其他对象取值的结果,
其他对象仍会得到实例变量
一开始就被赋予的值。

实例变量必须创建对象后
才可以通过这个对象来使用,
静态变量
则可以直接使用类名来引用。
32.垃圾回收器的基本原理是什么?
垃圾回收器是Java平台中用的
最频繁的一种对象销毁方法。
垃圾回收器会全程侦测Java应用程序的运行情况。
当发现有些对象成为垃圾时,
垃圾回收器就会销毁这些对象,
并释放这些对象所占用的内存空间。
在这里,程序开发人员需要知道,
在哪些情况下垃圾回收器
会认为这些对象是垃圾对象。
通常情况下,如果发生以下两种情况时,
系统会认为这些对象是垃圾对象,
需要销毁。
一是将一个NULL值赋值给对象。
二是对象其超出了作用范围,

 

33.垃圾回收器可以马上回收内存吗?
不会马上回收,
只有在必须回收时才会回收,
或者你可以调用垃圾回收方法,
虚拟机会在空闲时回收,
至于什么时候回收,
虚拟机说了算

 

34.有什么办法主动通知虚拟机进行垃圾回收?
对于GC来说,
当程序员创建对象时,
GC就开始监控这个对象的地址、
大小以及使用情况。 
通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象。
通过这种方式确定哪些对象是”可达的”,
哪些对象是”不可达的”。
当GC确定一些对象为”不可达”时,
GC就有责任回收这些内存空间。
可以。程序员可以手动执行System.gc(),
通知GC运行,
但是Java语言规范
并不保证GC一定会执行。

System.gc()的工作原理
Java中的内存分配
是随着new一个新的对象来实现的,
这个很简单,
而且也还是有一些
可以“改进”内存回收的机制的,
其中最显眼的
就是这个System.gc()函数。

乍一看这个函数似乎是可以进行垃圾回收的,
可事实并不是那么简单。
其实这个gc()函数的作用只是提醒虚拟机:
程序员希望进行一次垃圾回收。
但是它不能保证垃圾回收一定会进行,
而且具体什么时候进行
是取决于具体的虚拟机的,
不同的虚拟机有不同的对策。

 

35.内部类可以引用他包含类的成员吗?
完全可以。
如果不是静态内部类,
那没有什么限制! 
一个内部类对象可以访问
创建它的外部类对象的成员包括私有成员。
如果你把静态嵌套类当作内部类的一种特例,
那在这种情况下不可以访问外部类的
普通成员变量,
而只能访问外部类中的静态成员。

内部类的访问规则:
1、内部类可以直接访问外部类中的成员,
包括私有。
之所以可以直接访问外部类中的成员,
是因为内部类中持有了
一个外部类的引用,
格式 外部类名.this
2、外部类要访问内部类,必须建立内部类对象。

内部类定义在局部时,
1、不可以被成员修饰符修饰
2、可以直接访问外部类中的成员,
因为还持有外部类中的引用。
但是不可以访问它所在的局部中的变量。
只能访问被final修饰的局部变量。

 

36.Java 中的异常处理机制的简单原理和应用?
 一、Execption可以分为
java标准定义的异常
程序员自定义异常2种
1.一种是当程序违反了java语规则的时候,
JAVA虚拟机就会将发生的错误
表示为一个异常.
这里语法规则指的是
JAVA类库内置的语义检查。
例如 int i = 2 / 0 
或者 String str = null;str.length();

2.另一种情况就是JAVA允许程序员
扩展这种语义检查,
程序员可以创建自己的异常,
并自由选择在何时用throw关键字
引发异常。

例如 Exception ex = new Exception("这是我自定义的异常;
throw ex;

所有的异常都是Thowable的子类。
异常处理是与程序执行是并行的。

二、异常的处理方式
1.捕获异常

 try {
  int i = 2 / 0;
 } catch (Exception ex) {
   ex.printStackTrace();
   System.out.println("异常信息:" + ex.getMessage());
}

2.上抛异常 throws
public void test() throws Exception { 
    String str = null;
    str.length();
}

 

37.运行时异常与一般异常有何异同?
(1)运行时异常
都是RuntimeException类
及其子类异常,
如NullPointerException、
IndexOutOfBoundsException等,
这些异常是不检查异常,
程序中可以选择捕获处理,
也可以不处理。
这些异常一般是由程序逻辑错误引起的,
程序应该从逻辑角度
尽可能避免这类异常的发生。

当出现RuntimeException的时候,
我们可以不处理。
当出现这样的异常时,
总是由虚拟机接管。
比如:我们从来没有人
去处理过NullPointerException异常,
它就是运行时异常,
并且这种异常还是最常见的异常之一。

出现运行时异常后,
系统会把异常一直往上层抛,
一直遇到处理代码。
如果没有处理块,
到最上层,
如果是多线程就由Thread.run()抛出,
如果是单线程就被main()抛出。
抛出之后,
如果是线程,
这个线程也就退出了。
如果是主程序抛出的异常,
那么这整个程序也就退出了。
运行时异常是Exception的子类,
也有一般异常的特点,
是可以被Catch块处理的。
只不过往往我们不对他处理罢了。
也就是说,
你如果不对运行时异常进行处理,
那么出现运行时异常之后,
要么是线程中止,
要么是主程序终止。 

如果不想终止,
则必须扑捉所有的运行时异常,
决不让这个处理线程退出。
队列里面出现异常数据了,
正常的处理应该是把异常数据舍弃,
然后记录日志。
不应该由于异常数据
而影响下面对正常数据的处理。

(2)非运行时异常
是RuntimeException以外的异常,
类型上都属于Exception类及其子类。
如 IOException、SQLException 等
以及用户自定义的Exception异常。
对于这种异常,
JAVA编译器强制要求我们
必需对出现的这些异常进行catch并处理,
否则程序就不能编译通过。
所以,面对这种异常不管我们是否愿意,
只能自己去写一大堆catch块
去处理可能的异常。

 

38.为什么Map接口不继承Collection 接口?
Collection是最基本的集合接口,
声明了适用于JAVA集合(只包括Set和List)
的通用方法。 
Set 和List 都继承了Conllection;
Set具有与Collection完全一样的接口,
因此没有任何额外的功能,
不像前面有两个不同的List。
实际上Set就是Collection,只 是行为不同。
(这是继承与多态思想的典型应用:表现不同的行为。)
Set不保存重复的元素(至于如何判断元素相同则较为负责) 

 Map没有继承于Collection接口 
从Map集合中检索元素时,
只要给出键对象,
就会返回对应的值对象。 


Collection 和 Map 的区别
容器内每个为之所存储的元素个数不同。
Collection类型者,
每个位置只有一个元素。
Map类型者,
持有 key-value pair,
像个小型数据库

尽管Map接口和它的实现也是集合框架的一部分,
但Map不是集合,
集合也不是Map。
因此,Map继承Collection毫无意义,
反之亦然。
如果Map继承Collection接口,
那么元素去哪儿?
Map包含key-value对,
它提供抽取key或value列表集合的方法,
但是它不适合“一组对象”规范。

 

40.comparable 和 comparator的不同之处?
Comparable可以认为是一个内比较器,
实现了Comparable接口的类有一个特点,
就是这些类是可以和自己比较的,
至于具体和另一个实现了Comparable接口的类如何比较,
则依赖compareTo方法的实现,
compareTo方法也被称为自然比较方法。
如果开发者add进入
一个Collection的对象想要Collections的sort方法
帮你自动进行排序的话,
那么这个对象必须实现Comparable接口。
compareTo方法的返回值是int,
有三种情况:
1、比较者大于被比较者
(也就是compareTo方法里面的对象),
那么返回正整数
2、比较者等于被比较者,那么返回0
3、比较者小于被比较者,那么返回负整数


Comparator可以认为是是一个外比较器,
个人认为有两种情况
可以使用实现Comparator接口的方式:
1、一个对象不支持自己和自己比较
(没有实现Comparable接口),
但是又想对两个对象进行比较
2、一个对象实现了Comparable接口,
但是开发者认为compareTo方法中的
比较方式并不是自己想要的那种比较方式

Comparator接口里面有一个compare方法,
方法有两个参数T o1和T o2,
是泛型的表示方式,
分别表示待比较的两个对象,
方法返回值和Comparable接口一样是int,
有三种情况:
1、o1大于o2,返回正整数
2、o1等于o2,返回0
3、o1小于o2,返回负整数

总结
两种比较器Comparable和Comparator,
后者相比前者有如下优点:
1、如果实现类没有实现Comparable接口,
又想对两个类进行比较
或者实现类实现了Comparable接口,
但是对compareTo方法内的比较算法不满意,
那么可以实现Comparator接口,
自定义一个比较器,
写比较算法

2、实现Comparable接口的方式比
实现Comparator接口的耦合性要强一些,
如果要修改比较算法,
要修改Comparable接口的实现类,
而实现Comparator的类是在外部进行比较的,
不需要对实现类有任何修 改。
从这个角度说,
其实有些不太好,
尤其在我们将实现类的.class文件
打成一个.jar文件
提供给开发者使用的时候。
实际上实现Comparator 接口的方式
后面会写到就是一种典型的策略模式。

当然,这不是鼓励用Comparator,
意思是开发者还是要在具体场景下
选择最合适的那种比较器而已。

 

 

posted @ 2018-11-13 07:26  撩课学院  阅读(349)  评论(0编辑  收藏  举报