Java常见问题二

来源:互联网 发布:大数据主持词 编辑:程序博客网 时间:2024/05/17 08:32


1、Java对内存空间的划分:五部分

栈、堆、方法区,本地方法区、寄存器

1)栈内存:存储的都是局部变量,只要是在方法内定义的变量都是局部变量。一单变量生命周期结束,该变量就被释放。

2)堆内存:(1)存储的都是实体(对象)。(2)每一个实体都有首地址值。(3)堆内存中的变量都有默认初始化值,不同类型的初始化值不一样。如:int-0,double-0.0,boolean-false,char-'\u0000'。(4)当实体不再使用时,就会被垃圾回收机制处理。

3)方法区:方法、String常量池、静态区、代码区

4)本地方法区:跟系统相关的方法

5)寄存器:由cpu执行。

2、成员变量与局部变量的区别:

1)源代码中定义的位置不同

成员变量定义在类中。

局部变量定义在方法中(只要是类的下一级大括号都是局部的),也可以定义在语句中。

2)内存中的存储位置不同

成员变量存储在堆内存的对象中

局部变量存储在栈内存的方法中

3)生命周期不同

成员变量随着对象的加载而加载,随着对象的消失而消失

局部内存随着所属区间的运行出现,随着所属区间的结束而释放

4)初始化值得区别

成员变量有默认初始化值

局部变量没有默认初始化值,要先定义,赋值才能使用

3、查找变量遵循一个原则:就近原则

4、Java中参数传递问题

基本类型:形式参数的改变对实际参数没有影响。

引用类型:形式参数的改变直接影响实际参数。

string 是不可变的引用的类型,CLR在运行时进行了优化,相同的string实际上在内存中只存在一份

 

例:两个数组变量指向同一份资源,任一改变可修改它。Java中只有值传递,引用类型传递的是地址值。

5、面向对象思想特点:

1)面向对象是一个符合人们思考习惯的模式。

2)面向对象让复杂的事情简单化

3)面向对象让我们从执行者变为指挥者

4)面向对象是基于面向过程的

6、匿名对象的特点:

1)没有名字

2)用完就变成垃圾

7、方法重写和方法重载的区别:

方法重写:子父类中,出现方法相同的情况。返回值,方法名,参数

方法重载:同一个类中,方法名相同,参数列表不同,跟返回值无关。

1)子父类;同一个类

2)重写与返回值有关,重载无关。

8、数组和集合的区别:

1)数组时固定的,集合是可变的

2)数组中可以存储同一基本数据类型,集合中只能存储对象。

9、break与continue的异同

它们是在循环中使用的,一般是在循环中的判断中使用。它们下面不能跟代码,它们一般位于底部。

break用于种植当前循环,continue用于结束本次循环,进入下一次循环。

10、构造方法

1)方法名与类名一致

2)没有返回值类型

3)没有具体的返回值

 

注意事项:

1)如果没有给出构造方法,那么系统会默认给出一个无参构造函数

2)加入有定义了构造方法,系统不会再提供无参构造方法

3)构造方法重载,其实就是不同构造方法接收不同参数

11、this与super

this代表其所有方法所属对象的引用

super代表父类内存空间的标识。

12、构造代码块

1)定义在方法中的代码块

作用:让变量尽可能的从内存中消失,以提高效率

2)定义在方法外的代码块,把所有构造方法中的共通的内容定义在构造代码块中,提高代码复用性。

13、static

特点:

1)随着类的加载而加载

2)优先于对象存在

3)修饰的内容被同一类下所有的对象共享

4)可以直接被类名调用

 

1)静态变量:可以被该类下的所有对象共享

2)静态方法:(1)无this(2)静访静(3)静态内容有两种调用方式

14、内部类:

访问特点:内部类可以直接访问外部类中的成员,包括私有成员。而外部类要访问内部类中的成员必须要建立内部类的对象。

15、方法中的内部类能不能访问方法中的局部变量,为什么?

1)、不能,原因是:编译程序实现上的困难,难在何处:内部类对象的声明周期会超过局部变量的生命期。
 为什么?表现在:局部变量的声明期:当该方法被调用时,该方法中的局部变量在栈中被创建(诞生),
 当方法调用结束时(执行完毕),退栈,这些局部变量全部死亡。而:内部类对象生命周期,与其他类一样,
 当创建一个该局部类对象后,只有没有其他人再调用它时,它才能死亡。完全可能:一个方法一调用结束(局部变量已死亡),
 但该局部类的对象仍然活着。即:局部类的对象声明周期会超过局部变量。
 2)、将所有的局部内部类对象要访问的final型局部变量,变成该内部类对象中的一个数据成员。
 这样,即使栈中局部变量(含final)已死亡,但由于它是final,其值永不变,因而局部内部类对象在变量死亡后,
 照样可以访问final型局部变量。

16、继承

特点:

1)Java只支持单继承,不支持多继承,但支持多实现,但在接口与接口中,有多继承。

2)Java支持多层继承(戏称:族孙三代)

注意:

1)子类可以直接访问父类的非私有的属性和行为。

好处:

1)提高了代码的复用性

2)让类与类之间产生了关系,是多态的前提。

构造方法关系:

子类的构造方法默认都去访问了父类的无参构造方法:在子类中的构造方法中都有一行默认语句:super();因为子类会自动具备父类中非私有数据。那么,这个数据的初始化靠父类完成。所以,会先去调用父类的构造方法对数据进行初始化。

注意:如果父类中没有无参构造方法,那么,该怎么办呢?

1)可以通过super(参数)去访问父类的有参构造方法

2)可以通过this(参数)调用本类的构造方法,照样可以调用父类的。

17、静态代码块--》构造代码块-->构造方法

/* *  *  * 结果: * 理解子父类中初始化的详细过程 * * 运行main--->测试类中的main方法中创建子类对象 * new对象--->注意:只有运行期间,执行new 才会将对应的字节码文件加载到内存中 *父类字节码文件加载到内存---> 加载父类中静态内容(变量、方法) *子类字节码文件加载到内存---> 加载子类中静态内容(变量、方法) * 默认初始化父类变量--->给父类变量赋默认的初始化值 * 默认初始化子类变量--->给子类变量赋默认的初始化值 * 加载非静态父类成员方法--->因为只是加载到内存中,所以也可能实在默认初始化之前执行 * 加载非静态子类成员方法--->因为只是加载到内存中,所以也可能实在默认初始化之前执行 * 显示初始化父类成员(非静态变量、初始化块、静态初始化块)---->【按代码从上往下顺序】 * 父类构造---->执行父类中的构造方法 * 显示初始化子类成员(非静态变量、初始化块、静态初始化块)---->【按代码从上往下顺序】 * 子类构造--->执行子类中的构造方法 * 运行main中new对象后的语句--->程序结束 *  * 这道题的关键在于,子类会覆盖父类中的show()方法。 */public class Test {public static void main(String[] args) {Zi zi1 = new Zi();// 以下两步骤验证了只有执行new开始,才真正的开始加载字节码文件// Zi zi2;// new Zi();}}class Zi extends Fu {int xZi = 5;{show();// 对比2:这里的show()方法能正常执行,说明方法是在显示初始化之前加载的System.out.println("xZi=" + xZi);}static int xZi1 = 6;static {// show();// 对比2:这里的show()方法不能正常执行,说明方法的加载是在加载字节码文件之后执行System.out.println("xZi1=" + xZi1);}Zi() {System.out.println("Zi Begin");show();System.out.println("Zi End");}void show() {System.out.println("TEST-Zi");System.out.println("xZi=" + xZi + ";" + "xZi1=" + xZi1);}}class Fu {{test();}int yy = 10;void test() {System.out.println("yy=" + yy);}// 以上内容仅仅是为了进一步证明,默认初始化实在显示初始化之前执行,且方法加载到内存是在显示初始化之前执行int yFu = 29;{show();// 对比1:这里的show()方法能正常执行,说明方法是在显示初始化之前加载的System.out.println("yFu=" + yFu);}static int yFu2 = 30;static {// show();// 对比1:这里的show()方法不能正常执行,说明方法的加载是在加载字节码文件之后执行System.out.println("yFu2=" + yFu2);}Fu() {System.out.println("Fu Begin");show();System.out.println("Fu End");}void show() {System.out.println("TEST-Fu");System.out.println("Fu:y=" + yFu + ";" + "Y1=" + yFu2);}}

19、final关键字

1)final修饰的类不能被继承,但可以继承其他的类

2)final修饰的变量表示常量,只能赋值一次。

3)final修饰的方法不能被子类重写

20、抽象类

成员特点:

1)成员变量:可以有成员变量,也可以有常量

2)构造方法:有构造方法,可以用于子类访问父类数据前,对父类数据进行初始化。

3)成员方法:可以有抽象方法,也可以有非抽象方法。抽象方法,是为了要求子类做某些事情,非抽象方法是为了提高了代码复用性,被子类继承。

特点:

1)抽象方法和抽象类用关键字abstract表示

2)有抽象方法的类一定是抽象类(或者接口),抽象类中不一定有抽象方法。

3)抽象类不能被实例化

4)如果一个类继承抽象类,那么这个类重写父类的所有抽象方法,要么本身也是抽象类。作用:强制要求子类必须完成某些功能。

21、接口

成员特点:

1)成员变量:接口中只有常量。因为接口的成员变量有默认修饰符。public static final

2)构造方法:没有构造方法。

3)成员方法:接口中的方法都是抽象的。因为接口中的成员方法又默认修饰符。public abstract

特点:

1)接口不能被实例化

2)接口中的方法要么被子类实现,要么子类时抽象类

3)接口是对外暴露的规则

4)接口是程序的功能扩展

5)接口的出现降低耦合性

6)接口可以用来多实现,它也可以多继承接口

22、多态

前提条件:

1)要有继承关系或实现关系

2)要有方法重写

3)要有父类引用指向子类对象

成员特点:

1)成员变量:编译看左边,运行也看左边

2)成员方法:编译看左边,运行看右边

好处和弊端

1)好处:可以提高代码的扩展性和可维护性

2)父类引用不能使用子类特有功能

23、访问修饰符

                              本类               同一包              子类               全局范围

private                    yes

默认                       yes                  yes

protected               yes                  yes                  yes

public                     yes                  yes                  yes                      yes

 

常用规则如下:

以后,所有的类都用public修饰。并且,在一个java文件中,只写一个类。

以后,所有的成员变量用private修饰。

以后,所有的成员方法用public修饰。如果是抽象类或者接口。

以后,所有的构造方法用public修饰。如果类是工具类或者单例类,构造用private修饰。

24、关于Integer的面试题

byte常量池,也就是byte范围内的值,直接赋值给Integer,是从常量池里面获取的。-128~127.它有关系到一个设计模式:享元设计模式。

25、集合和数组的区别?

数组:

1、数组长度固定

2、数组可以存储基本数据类型,也可以存储引用类型

3、数组存储的数据类型是一致的

集合:

1、集合长度可变

2、集合只能存储引用类型

3、集合可以存储不同类型的对象

26、并发修改异常

 当我们通过迭代器迭代元素的过程中,又通过集合去添加了元素。这种情况是不允许的。因为迭代器是依赖于集合存在的,如果集合发生改变,迭代器也应该相应的发生改变。而我们目前看到的确实,迭代器没变,集合变了。所以,报出了一个并发修改异常。

     注意问题:通过迭代器遍历集合的时候,是不能通过集合去操作(添加、操作)

那么我们可不可以这么理解呢?

A:全部通过迭代器操作:元素是添加到刚遍历的哪个元素后面。通过迭代器迭代的时候,可以通过迭代器对集合进行操作。

B:全部通过集合操作,元素是添加到最后的。

通过集合普通for遍历的时候,可以通过集合去操作。

27、哈希表

用于存储元素和哈希值对应关系的容器

特点:

(1)不允许存储重复元素,因为会发生查找的不确定性。

(2)不保证存入和取出的顺序一致

(3)比数组的查询效率高

 

哈希表在判断元素是否相同:

依据hashCode方法。如果哈希值重复(相同,哈希冲突),再判断元素的equals方法。如果equals返回true,不存在,返回false存储

28、一些数据结构的特点

堆栈:先进后出(弹夹)

队列:先进先出(水管)

数组的优缺点:查询快,增删慢,重新创建一个数组

链表:把一些节点通过链子连接起来的数据结构

结点:由地址(指针)域和数值域组成。

优缺点:增删快,查询慢

29、List    

 ArrayList:底层数据结构是数组,查询快,增删慢,是不同步,不安全的,效率高。

Vector:底层的数据结构是数组,查询快,增删慢,线程安全,效率低

LinkedList:底层是局结构是链表,查询慢,增删快,是县城不安全的,效率高。

30、LinkedList   

都通过LinkedList模拟栈数据结构,它的特点是:先进后出,可用addFirst和removeFirst方法模拟

31、泛型   

任意的类型。是一种用把明确数据类型的工作放在了创建对象或者调用方法时候进行的特殊的类型。

好处:

(1)解决黄色警告线问题

(2)把运行期间的类型转换异常提前到了编译期间

(3)优化程序设计

32、Collection与Collections的区别?           

Collection:是Collection集合的顶层接口,定了Collection集合的共性方法

Collections:是一个类,定义了Collection集合操作的功能。有排序、查找、反转、随机换位等。                                                                                                                                          

33、HashMap和Hashtable的区别     

 HashMap是线程不安全的,效率高,允许null键和null值

Hashtable是线程安全,效率低。不允许null键和null值

34、递归

方法定义调用方法本身的现象

直接递归:直接本方法内调用本方法

间接递归:本方法调用别的方法,别的方法调用本方法

 注意事项:

(1)递归一定要有出口,否则就会内存溢出,也就是死循环

(2)递归的次数不要过多,否则内存溢出

35、为什么要有close()呢?      

(1)让流对象变成垃圾

(2)通知系统去释放和文件相关的资源

(3)刷新缓冲区

36、   

(1)为什么FileWriter没有无参构造方法?

因为写数据的时候,一定要明确写到那哪里去

(2)flush()和close()的区别?

flush():只刷新缓冲区,流对象还可以继续使用。

close():先刷新缓冲区,在关闭流对象,流对象不可以继续使用

(3)难道每次调用方法的时候,都需要刷新吗?或者说,不用刷,直接等到close()来解决,行不行?

这两种方式都不可取

37、java只有值传递

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递
值传递:java只有值传递。
 A基本类型的值,传递的就是指
 B引用类型的值,传递的是地址值                                                                                                                                                                                                                                                                                 

 

38、异常      

  注意:

前提:父类中要被重写的方法中没有抛出异常

当子类实现父类中方法的时候,在事项过程中如果出现编译时异常时,只能通过try..catch

当子类实现父类中方法的时候,在实现过程中如果出现运行时异常时,

由于运行时异常其实已经默认抛给虚拟机,及所有方法已经默认将运行时异常抛出,

所以,对于运行时异常子类可以声明或者try...catch...

 

如果父类中要被重写的方法跑出了该异常,那么注意,子类中抛出的异常类型要小于等于父类的异常                                                                                                                                                             

0 0
原创粉丝点击