java开发面试问答----基础篇

重写和重载的区别

  • 重写(Override)是子类对父类的容许访问的方法的实现过程进行从新编写, 返回值和形参都不能改变
  • 重载(overloading)是在一个类里面,方法名字相同,而参数不一样。

抽象类和接口有什么区别

  • 抽象类是类的抽象,目的在于找出类的共同点,抽象类的不一样点,接口是行为的抽象,每一个行为的具体实现都是不一样的。
  • 实现上,抽象类能够有构造函数和普通成员变量
  • 一个类只能继承一个抽象类,可是能够实现多个接口

反射的用途和实现

  • 反射用于在jvm运行过程当中动态的获取对象的类信息,一般用于框架开发如spring
    • 判断任意一个对象所属的类
    • 构造任意一个类的对象
    • 判断任意一个类所具备的成员变量和方法,包括private,好比idea的输入提示
    • 调用任意一个对象的方法
  • 实现能够经过对象的getclass方法获取类,或者使用class包的class.forname经过类路径找到类,而后可使用class的newInstance方法建立新的对象,也能够经过获取类的constructor对象使用指定的构造函数建立对象。

int 和 Integer 有什么区别

  • Integer是int的包装类,int则是java的一种基本数据类型
  • Integer实际是对象的引用,当new一个Integer时,其实是生成一个指针指向此对象;而int则是直接存储数据值
  • Integer的默认值是null,int的默认值是0

equals 和 == 有什么区别

  • == 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,便是否是指相同一个对象。比较的是真正意义上的指针操做
  • equals用来比较的是两个对象的内容是否相等

Integer使用==和int型比较为何在127如下是相等的而128不等

当Integer和int比较时,java会自动对int装箱(Integer.valueOf),因为大多数int比较都在128如下,所以java将-128到127的数放入了缓存,返回的是缓存中的同一个对象而不是新的对象java

类加载,隔离机制

类加载的过程

类加载主要有三个过程,装载,链接,初始化;装载是指查找和导入class文件到内存中,链接则是根据class二进制数据生成对象,这里会进行类的校验保证数据符合jvm规范,静态变量内存分配和符号引用的解析;初始化则是类的初始化操做,这里会进行静态变量和静态代码块的初始化,执行类的构造器。面试

双亲委派机制

jvm中有三类加载器,启动类加载器,扩展类加载器和应用类加载器,双亲委派机制是说当应用类加载器须要加载一个类时不会直接加载而是到父加载器中查找,找不到就找祖加载器,只有都找不到时才会本身加载。spring

隔离机制

每一个类加载器都有本身的加载范围以保证内存隔离,对于同一个类的评判标准是:类名一致,类加载器一致,类加载器实例一致。数据库

若是黑客手写了一个string.class用自定义加载器加载会生效吗

不会生效,由于父类加载器已经加载了string.class,当其余类加载时会直接加载系统的string.class设计模式

多线程环境如何保证只有一个class对象

扩展类加载器在加载类时使用了concurrentHashMap和synchronized,concurrentHashMap保证了只有一个线程能往里面放对象,而synchronized则保证了加载时只有一个类能被加载数组

如何破坏双亲委派

自定义类加载器一般是继承扩展类加载器,实现自身findclass方法,若是要破坏双亲委派则要重写loadclass方法缓存

序列化方式

有两种方式,一种是使用OutputStream类的wirteobject方法,二种是实现Serializable接口安全

如何判断一个文件是否存在,如何读取一个目录下的全部文件和子目录

建立file类对象,调用exist方法判断是否存在,并使用isfile方法判断是不是文件仍是目录,目录的话可使用listfile列出目录下全部文件和子目录数据结构

nio aio bio

  • bio,同步阻塞io:客户端发起一个请求,服务端起一个线程处理请求
  • nio,同步非阻塞io:客户端发起一个请求时,服务端生成一个channel创建链接,channel注册到多路复用器上,selector扫描channel,当channel有数据写到buffer时扔给线程处理
  • aio,异步非阻塞io:客户端发起一个请求时,服务端标记这个io,当系统处理完时回调服务端,服务端处理这个请求

select poll epoll

三种系统的io处理模式,他们都是同步io,使用的多路复用器,当有流须要处理时必须本身处理。多线程

  • select 和nio很像,当有流须要io处理时,轮训多路复用器上全部的文件描述符,每一个文件描述符对应一个socket,找到须要处理的流
  • poll 是对select的优化,select因为在用户空间操做,每一个端口对应的链接数有限制,而poll是将数据移到内核空间处理,只须要检查文件描述符对应的设备状态便可,由于处理链表存储fd所以没有链接数的限制
  • epoll 则是对poll的优化,当有流进来时会生成io事件通知,而后进程处理对应的io事件,当fd就绪时内核会经过回调激活fd

堆,栈,gc

jvm的做用

java代码编译成.class存在操做系统兼容问题,而jdk是根据操做系统安装的,因此jdk中的jvm加载class文件能够屏蔽掉操做系统的兼容性问题

jmm是什么

jmm是java内存模型,和cpu硬件结构类似,每一个线程有本身的工做内存空间,并与主内存交互,当有新的变量时首先写入主内存而后拷贝到工做内存,好处是能够提升处理速度,而且线程之间内存隔离。

堆,栈

堆存放动态产生的数据,如new的对象,而栈存放局部变量,包括基础数据类型的值和对象的引用

一次gc的过程

堆分为新生代,老年代,永久代(常量池,元数据),java 内存分配和回收的策略是分代分配分代回收,java young gc采用的是中止-复制清理法。新生代分为eden区和两个存活区,当一个对象被建立时首先分配到eden区中,当eden区满时触发young gc将消亡的对象清理掉并把存活的对象复制到存活区0;以后,young gc在清理eden的同时清理存活区0,把存活的对象复制到存活区1,此时存活区0清空;如此反复,两个存活区总有一个是空的,每切换一次存活对象的年龄加1,当屡次切换后(默认年龄是8)仍存活的对象将复制到老年代;当老年代满时触发full gc。若是存入eden区的对象很是大,超过eden区的大小则会直接放入老年代。

如何主动触发gc

jvm判断是不是垃圾对象用的是可达性分析法,判断这个对象是否有引用; 使用system.gc主动触发full gc;

jvm相关命令jstak,jmap,jstat,如何dump内存

  • jstat:内存管理工具,能够查看gc和当前内存使用统计状况;
  • jstack:用来跟踪堆栈,分析当前程序的运行状况 ,能够dump出当前的堆栈信息
  • jmap:能够dump出堆信息,分析当前gc状况。

排查频繁gc

  • 思路:引发gc的缘由一般有2类,一类是内存泄漏,一类是大对象存储,所以能够从这2个方向去排查问题
    • 首先jmap dump出内存文件,jstack dump出堆栈信息
    • 使用MAT工具分析内存dump文件,找到大量建立的对象和内存占用最大的对象
    • 到堆栈dump信息中找寻问题对象相关的堆栈信息还原现场
    • 优化代码,针对内存泄漏修改代码逻辑及时释放对象,针对大对象要分拆

数据结构

ArrayList, LinkedList, SynchronizedList and Vector, CopyAndWriteArrayList

ArrayList, LinkedList 和Vector都实现了List接口,区别在于:

  • ArrayList内部其实是一个数组,当更多元素加入时,其大小会动态的增加,每次增加50%,在使用时若是能预估数组的大小进行初始化,能大幅减小调整容量的开销。
  • LinkedList内部是一个双链表,其和ArrayList相比优点在于增删操做比较快,而get和set操做比较慢
  • Vector和ArrayList同样内部是一个数组,区别在于Vector是线程安全的,当Vector数据增加时默认每次扩容一倍可是长度可控。
  • SynchronizedList和Vector同样是线程安全的,他的区别在于能够将任意List转成线程安全的类,可是缺点在于其内部实现机制上遍历操做不是线程安全的须要手动加锁。
  • CopyAndWriteArrayList是对vector作的优化,vector使用Synchronized锁住读写操做,而CopyAndWriteArrayList不锁读操做,写操做时使用lock上锁当写操做完成时替换整个array。

HashMap原理

  • hashmap concurrenthashmap
    • hashmap
      • java7是由数组和链表组成的,每个数组元素存的是entry
      • get: 根据key的hash值找到数组的位置,而后比较链表中每一个元素的key获得value
      • put: 根据key的hash值找到数组的位置,而后比较链表中是否存在该key,没有存在则将该 entry存入链表
      • resize: hashmap初始化时有数组容量和负载因子,负载因子默认0.75,当数组中存放个数大 于容量*负载因子时进行扩容操做容量翻倍
      • java8加入红黑树,当链表长度大于8时会变成红黑树
    • concurrenthashmap
      • 采用分段设计,每一个段其实就是一个加了同步锁的hashmap
  • ConcurrentHashMap 和 hashtable
    • hashtable同步会锁住整个数据,而ConcurrentHashMap采用分段设计,每次只会锁住一段数据
相关文章
相关标签/搜索