java常见面试题

1.private修饰的方法可以通过反射访问,那么private的意义是什么
  private只是在oop(Object Oriented Programming)编程中起约束作用,体现了封装性,外部对对象进行常规调用时能够看到清晰的类结构
java也有专门的安全管理器SecurityManager禁止反射,但也可以获取java的bytecode进行修改,如果真要做到安全性,可以做个server,用接口来限制访问.

2.Java类初始化顺序(基类就是父类,派生类就是子类)
  基类静态代码块,基类静态成员变量(根据代码中顺序,只在第一次加载时执行)>
  派生类静态代码块,派生类静态成员变量>
  基类普通代码块和成员变量(并列优先级)>
  派生类普通代码块和成员变量>
  基类构造函数>
  派生类构造函数

3.对方法区和永久区的理解以及它们之间的关系
方法区(Method Area)是jvm规范里面的运行时数据区的一个组成部分,jvm规范中的运行时数据区还包含了:pc寄存器、虚拟机栈、堆、方法区、运行时常量池、本地方法栈。
主要用来存储class、运行时常量池、字段、方法、代码、JIT代码等。
注意:
(1)运行时数据区跟内存不是一个概念。
(2)方法区是运行时数据区的一部分
(3)方法区是jvm规范中的一部分,并不是实际的实现,切忌将规范跟实现混为一谈。
永久带又叫Perm区,只存在于hotspot jvm中,并且只存在于jdk7和之前的版本中,jdk8中已经彻底移除了永久带,jdk8中引入了一个新的内存区域叫metaspace。
(1)并不是所有的jvm中都有永久带,ibm的j9,oracle的JRocket都没有永久带。
(2)永久带是实现层面的东西。
(3)永久带里面存的东西基本上就是方法区规定的那些东西。
结论:方法区是jvm规范里要求的,永久区是Hotspot虚拟机对方法区的具体实现,前者是规范,后者是实现方式
(1)方法区是规范层面的东西,规定了这一个区域要存放哪些东西
(2)永久带或者是metaspace是对方法区的不同实现,是实现层面的东西。

4.局部变量使用前需要显式的赋值,否则编译通过不了,为什么这样设计?
  这样设计是一种约束,局部变量而言,其赋值和取值访问顺序都是确定的,而成员变量是可以不经初始化的,在类加载过程的准备阶段即可给它赋予默认值
  其赋值和取值访问阶段先后顺序都具有不确定性
  扩展:非静态的成员变量的默认赋值是在类加载时

5.Vector与ArrayList的区别:
  Vector与ArraryList都是lsit接口的实现类,它们都代表链式形式的数据结构,
  它们都是通过一个对象数组来存储元素,但vector的大多数方法都是线程安全的,因为都加了synchronized关键字,但arraylist的效率更高

6.HashMap和HashTable的区别(保存元素时,都是无序的)
  一.HashTable的方法是同步的,HashMap不能同步
  二.HashTable不存在null值,HashMap可以有null值
  三.HashTable有一个contains方法
  四.HashTable使用Enumeration遍历,HashMap使用Iterator遍历
  五.Hashtable中的hash数组默认大小为11,增加的方式为:old*2+1.HashMap中hash
数组默认为16,而且一定时2的指数
  六.HashTable直接使用对象的hashCode,而HashMap会重新计算hash值

7.java中的不可变类
不可变类就是一旦被实例化就不会改变自身状态的类
String就是典型的不可变类,不可变类的主要用途是在多线程的环境下确保对象的线程安全

8.java中的虚函数代指抽象方法,抽象方法不能用private,static,synchronized,native等修饰符修饰
且抽象方法只是不能被重写,能被重载

9.关于对方法传参时,参数是否改变的理解:
传参数为String类型和基本数据类型时,相当于传了副本,方法中副本的改变不影响原先的值,
而其他类型的参数则因传的是值,所以方法中的改变也会造成原对象改变

10.如何创立,new线程对象:
  1)继承Thread类,重写里面的run方法,可以直接new对象
  优点:
    里面提供了很多关于线程的其他方法,fx:获取线程的id,线程名,线程状态
  缺点:
    让线程访问同一变量时,需使线程类变成内部类,去访问外部类的非静态成员变量,且不能在继承其他类
  2)实现Runnable接口,重写里面的run方法,是将实现Runnable接口的实现类对象给Thread类的构造器构造出一个线程类
  优点:
    能继承其他类,能更方便访问同一变量

11.sychronized实现线程同步
每个对象都有线程锁,sychronized可以用任何一个对象的线程锁来锁住一段代码块或方法
线程方法只需加一个sychronized修饰词,且它使用的是当前this对象的对象锁
注:如何线程中使用了wait()和notify()方法则需加上sychronized关键字

12.反射的了解:
反射的出发点在于jvm会为每个类创建一个java.lang.Class类实例,此实例中包含了属性(Field),方法(Method),构造器(Constructor),修饰符(Modifier)等信息.
在动态获取这些信息后,开发者能通过java.lang.reflect包下的api来反射出类实例,调用类的方法

13.反射中Class类的了解

首先Class是用来记录类的各种信息的,它伴随着类的加载而创建
一.那什么时候类才会加载进jvm中呢?
  1)直接使用该类创建对象
  2)访问该类的静态成员
  3)使用Class类的静态方法forName(),动态加载一个指定全包名的类
  例如:jdbc导入驱动类,就是Class.forName()的例子
二.那怎样拿到Class对象呢
  1)Class的forName()方法返回的就是Class类型
  2)每个类都有一个静态属性class,fx:Student.class就能直接拿到student的class对象
  3)Object类中有一个getClass的成员方法,能拿到指定对象的class对象 fx:stu.getClass().
  获取class对象后,能调用它的一些成员方法来获取它所代表的类的属性,方法等,以及调用newInstance方法来创建新的实例对象
  注: class中的方法举例: getName(),getMethod(),getConstructor(),newInstance()

14.反射中Class类中成员变量Field类的理解
  Field通过Class类的getDeclaredField()或getDeclaredFields()方法获取,其中的getXx,setXx能拿取指定对象的属性,因为都需要提供相应的实例对象
  注:能通过此方法能反射去改变类中的不提供get/set的私有属性

15.反射中class类中Method类的理解
  Method对象能通过Class类的getMethod()或getMethods()方法获取到,也可用方法名作为参数getDeclaredMethod()方法找到特定方法,获取它能提供类或接口中的方法
  Method类中使用最多的是invoke(),第一个参数为class所代表类的一个实例对象,后面则为不定长的参数列表用于放取方法所需的参数

16.通过反射实例化一个类
  首先,如果想让默认构造器直接构造对象,则直接使用Class类的newInstance方法即可,如果需要用其他有参的构造函数则需用Class类的getConstructor()(里面传参为class实例)得到相应的
Constructor对象后,在通过它的newInstance方法来创建对象,此方法的参数列表和构造方法的参数列表一样

17.如何利用反射机制来访问一个类的私有成员
  使用反射机制访问私有成员时,它的可访问性为false,需调用setAccessible(true),把原本不可访问的私有成员变得可访问后,
直接用getDeclaredField()方法里面传上方法名拿到特定的私有属性

原文地址:https://www.cnblogs.com/nyhhd/p/12546120.html