Java基础面试题大全

面试的过程中基础是很重要的一环,在此总结了一下我在面试过程中遇到的基础性问题,希望能在你们面试的过中锦上添花。
1.jdk jre jvm三者之间的关系
java开发者工具包   java运行环境   java虚拟机
jdk>>jre>>jvm
JDK是Java开发工具包,是Sun Microsystems针对Java开发员的产品。
JDK中包含JRE,在JDK的安装目录下有一个名为jre的目录,里面有两个文件夹bin和lib,在这里可以认为bin里
的就是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib和起来就称为jre。
就是我们常说的java虚拟机,它是整个java实现跨平台的最核心的部分,所有的java程序
会首先被编译为.class的类文件,这种类文件可以在虚拟机上执行。  
2.面向对象(oop)
面向对象是对面向过程的封装,封装了类的属性和方法
面向对象是把整个需求按照特点、功能划分,将这些存在共性的部分封装成对象,创建了对象不是为了
完成某一个步骤,而是描述某个事物在解决问题的步骤中的行为
面向过程就是分析出实现需求所需要的步骤,通过函数一步一步实现这些步骤,接着依次调用即可
3.对象创建的过程
对象创建之前,首先
类被加载(先加载父类再加载子类)
,执行静态代码块,
执行构造器((先构造父类再构造子类)),
创建对象实例静态方法和类有关,直接使用类名.方法来进行调用
4.java的反射机制
当类加载器将类加载进jvm之后,jvm会创建每一个类的元数据对象(Class),java语言允许通过元数据对象动态的创建对象实例,
这种机制就称为java的反射机制,基本上所有框架的底层都用到了反射机制,spring、mybatis、servlet都用到了.
Java中要用到反射,首先就必须要获取到对应的class对象,在Java中有三种方法获取类对应的class对象。
1、通过类的.class属性
2、通过类实例的getClass()方法获取
3、通过Class.forName(String className)方法获取
5.抽象类和接口有什么区别?(问的很多)
  抽象类当中可以有普通方法,必须有抽象方法,可以有成员变量,不可以被实例化接口当中只能有抽象方法,
  不能有普通方法,可以有静态常量,不可以被实例化,接口可以看做是一种特殊的抽象类
6.方法的重写与重载有什么区别?
重载是在同一个类中,方法名相同,参数列表不同的方法
重写是子类继承父类,返回值类型和参数列表与被重写的方法相同
重写方法的规则:

1)、参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。

2)、返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。

3)、访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)

4)、重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:

父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。

 

而重载的规则:

1)、必须具有不同的参数列表;

2)、可以有不同的返回类型,只要参数列表不同就可以了;

3)、可以有不同的访问修饰符;

4)、可以抛出不同的异常
7.java当中的多态是什么?
多态是指可以创建父类对象的引用指向子类的对象,方法的调用只能调用父类的方法
8.框架是如何反射创建对象的呢?
框架的配置有xml形式、注解形式
xml可以被解析,解析的技术有dom4j、sax解析

三大框架使用的解析方式是dom4j。

9.集合类(重点)
9.1常用的数据结构 数组和链表
9.2数组和链表有什么区别?
数组会在内存当中开辟一块连续的存储空间,需要指定长度
	数组当中的每一个元素都有索引,查询的话通过索引可以直接定位到
	某一个元素,效率很高,但是进行删除的话,数组会进行移动,所以效率很低.
	链表不需要连续的存储单元,链表中的上一个元素通过指针指向下一个元素,所以链表结构进行查询的话,
	头部尾部比较快,中间元素查找速度比较慢,但是删除的话,只需要删除前后指针,重新建立指针就可以了,
	所以删除的性能很高.
9.3 java当中的集合类或集合框架(重点)
 collection接口是集合类的顶层接口,collections是工具类
 collection有两个子接口,一个list接口,一个是set接口
 list接口有序可重复,set接口无序不可重复
 list接口常用的实现类有
 arrayList  基于数组实现的
 linkedList 基于链表实现的  区别参考数组和链表区别
 vector     基于数组实现的,但是是线程安全的(synchronized) 线程安全:指多个线程在执行同一段代码的时候采用加锁机制,使每次的执行结果和单线程执行的结果都是一样的,不存在执行程序时出现意外结果。
线程不安全:是指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。
 copyOnwriteArrayList   复制数组副本来实现的
 set接口常用实现类
 HashSet  基于hashMap来实现的,实现不可重复是通过 hashCode方法和equals方法进行两次比较,先比较hashCode,再通过equals
 TreeSet  基于二叉树来实现的,可以对元素进行排序(排序规则默认是自然顺序,可以自定义比较器,实现自定义排序)
arrayList和copyonwriteArrayList的区别:
arrayList底层是数组,插入时会先判断容量是否足够,如果不够会进行扩容(新建一个数组,将原有的数据复制到新数组里面)删除时数组元素会进行移动
copyOnwriteArrayList:实现了List接口,内部持有一个ReentrantLock lock = new ReentrantLock();底层是用volatile transient声明的数组 array,读写分离,写时复制出一个新的数组,完成插入、修改或者移除操作后将新数组赋值给array

Map接口(key value结构的)
map接口的实现类
HashMap  key不可重复,无序,可以为null       
实现原理  基于数组和链表来实现的
当存入一组键值对的时候,先对key进行hash,然后映射到一个初始化长度为16的数组上,当不同的key产生hash碰撞的时候,value会通过链表结构来进行存储,jdk1.8之后对hashMap进行了改进,当链表长度达到临界值8,会通过红黑树来存储value,hashMap有两个参数,一个是初始化数组长度16,负载因子0.75,当满足扩容阈值的时候(当数组的12个元素被存满,并且有hash碰撞了),动态扩容,以2倍的增长方式进行扩容.
HashTable
HashTable是线程安全的hashMap(synchronized机制)key不准许为null
TreeMap基于二叉树来实现的,可对key进行自然排序(自定义比较器,写比较规则)
ConcurrentHashMap是线程安全的,对整个hash桶采用分段策略,拆分成若干个段segment,对每一个段上锁(synchronized),极大的提高了并发修改的效率.
10.线程
10.1进程和线程有什么区别?
进程是指应用程序在运行时的状态,进程会占用系统的cpu以及内存资源
线程是指进程当中的执行流程,多个线程协同工作,会共同使用进程的资源,
才确保进程的功能得以实现.
10.2 java当中如何实现线程呢?
1:继承Thread类
2:实现runnable接口,只是任务类,还需手动创建线程对象
3:线程池机制来创建和管理线程 ThreadPool
  singleThreadPool  创建一个线程的线程池
  fixedThreadPool   创建固定数量的线程池 
  cachedThreadPool   数量可缓存的线程池
  ScheduledThreadPool  有定时功能的线程池
10.3线程的生命周期
新建状态(new一个线程的时候)
   调用线程.start方法的时候,等待cpu分配时间片
可运行状态
   当cpu分配到了时间片之后,线程开始运行,运行run方法当中的内容
运行状态
   当线程遇到sleep、wait等方法的时候,线程会进入阻塞状态
阻塞状态
   当休眠时间到期,或者被notify了,线程又回到了可运行状态
死亡状态
   线程运行结束之后,就会销毁,被jvm的gc回收
10.4多线程并发或线程安全问题如何解决?(重点)
   1:通过volatile 关键字修饰变量,可以实现线程之间的可见性,
     避免变量脏读的出现,底层是通过限制jvm指令的重排序来实现的
     适用于一个线程修改,多个线程读的场景
   2:通过synchronized锁(任意对象)来实现线程同步,自动锁的思想,
     底层实现原理:当有线程进入同步代码块之后,利用jvm的计数器将
     锁的标记置为1,当别的线程再想进入的时候,发现锁的标记为1,
     该线程就去锁池等待,当第一个线程出来之后,锁的标记会置为0,
     之后cpu会随机分配一个线程再次进入同步代码块.
   3:通过lock锁的机制,进行手动lock,和unlock,但是这种很容易出现死锁。
 注意加锁以及解锁的顺序,就可以避免死锁

   4:通过线程安全的集合类,可以解决并发问题4
     ConcurrentHashMap
     CopyonWriteArrayList
   5:使用并发包下面的原子类,底层使用的是cas机制(乐观锁),可以解决并发问题 atomicInteger  线程安全的原子整型类
   6:使用线程池来创建和管理线程,也可以一定程度上解决并发问题
   7:使用ThreadLocal来修饰变量,可以解决并发问题
       ThreadLocal底层是怎么实现的?
       多个线程会复制一份threadLocao变量的副本进行操作,互不影响,来保证线程安全的
10.5线程之间如何进行通信?
  1:使用synchronized锁的wait和notify进行等待和唤醒
  2:使用lock锁的condition的await和signal进行等待唤醒
10.6悲观锁和乐观锁
悲观锁的思想对线程并发持悲观态度,使用互斥锁的机制来解决并发问题
乐观锁的思想是使用cas(compareAndSwapper)机制,不上锁,但也能解决并发问题
int count=100;
最后一次修改的时间戳或者版本号;
1:先查询一下变量的值以及它的最后一次修改的时间戳;
2:在本地修改变量的值
3:对变量进行修改的时候,先比对一下最后一次修改的时间戳是否发生变化了,如果没发生变化,修改变量的值, 如果发生变化了,重试以上流程

线程的使用场景:
   1:项目当中使用线程池(注册完毕发邮件和短信)
   2:tomcat本身就是通过线程的机制来处理用户的请求
IO(input输入 output输出)
  数据存储的形式
    文件形式   类似于湖泊
    IO流的形式  类似于河流
    File file=new File("d:\\1.txt");
    FileInputStream in=new FileInputStream("d:\\1.txt");
  java当中IO流的分类
      字节流  InputStream(抽象类)  OutputStream
           FileInputStream FileOutputStream (实现类)
      装饰者模式对传统的字节流进行了封装,增加了缓冲区功能
      BufferedInputStream  BufferedOutputStream(带有缓冲区的字节流)
  字符流  Reader       writer
          FileReader  FileWriter
      BufferedReader  BufferedWriter

猜你喜欢

转载自blog.csdn.net/he19970408/article/details/107768957