JAVA基础面试部分(多线程、算法、网络编程提出去了,详细分类见《面经》)
一、Java底层基础题
JDK和JRE区别?
1.JDK是整个JAVA的核心,包括了Java运行环境JRE,一堆Java工具和Java基础的类库。
通过JDK开发人员将源码文件(java文件)编译成字节码文件(class文件)。
2.JRE是Java运行环境,不含开发环境,即没有编译器和调试器。将class文件 加载到内存准备运行。
初始化与清理
抽象类与接口的区别是什么?
https://baijiahao.baidu.com/s?id=1620965468190584914&wfr=spider&for=pc
Java中存储金额用什么数据类型?
3 * 0.1 == 0.3 将会返回什么?
final关键字,抽象类可以使用final修饰吗?
1.用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的 值无法被改变。
对于成员变量来讲,必须在声明时或者构造方法中对它赋值;
2.修饰方法,表示该方法无法被重写;
3.修饰类,表示该类无法被继承。
抽象类是被用于继承的,final修饰代表不可修改、不可继承的。所以不能用final修饰抽象类。
java.util.Date和java.sql.Date的区别?
共同点:都有getTime方法返回毫秒数,可以直接构建
不同点:
1、java.sql.Date是针对SQL语句使用的,它只包含日期而没有时间部分,一般在读写数据库的时候用
PreparedStament的setDate()的参数和ResultSet的getDate()方法的都是java.sql.Date
2、java.util.Date是在除了SQL语句的情况下面使用,一般是日常日期字段
3、java.util.Date 是 java.sql.Date 的父类,
即:继承关系:java.lang.Object --》 java.util.Date --》 java.sql.Date
二、异常
三、反射:
RTTI、
构造器
了解反射吗?怎么用?用在哪里?
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。
总结说:反射就是把java类中的各种成分映射成一个个的Java对象,并且可以进行操作。
Java反射的原理:java类的执行需要经历以下过程:
编译:.java文件编译后生成.class字节码文件
加载:类加载器负责根据一个类的全限定名来读取此类的二进制字节流到 JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对 应的java.lang.Class对象实例 链接 验证:格式(class文件规范) 语义(final类是否有子类)
操作准备:静态变量赋初值和内存空间,final修饰的内存空间直接赋原值,此处不是用户指定的初值。解析:符号引用转化为直接引用,分配地址 初始化:根据程序员通过程序指定的主观计划去初始化类变量和其他资源, 或者可以从另一个角度来表达:初始化阶段是执行类构造器
怎么用:
//1、通过class.forName(),加载某个类。
//2、在运行时构造任意一个类的对象。
1 Class cls = Class.forName("com.jdk");
2 jdk jdkobj = cls.newInstance();
//3、在运行时判断任意一个类所具有的成员变量和方法。
1 Class cls = Class.forName("com.jdk");
2 Methods methods[]= cls.getDecliedMethod();
3 Fields fields[] = cls.getDeclieredFields();
使用场景:Class.forName();数据库注册驱动的时候。编译器智能提示该类有哪些方法可供调用。
AOP动态代理。经典的就是在xml文件或者properties里面写好了配置,然后在Java类里面解析 xml或properties里面的内容,得到一个字符串,然后用反射机制,根据这个字 符串获得某个类的Class实例,这样就可以动态配置一些东西,不用每一次都要 在代码里面去new或者做其他的事情,以后要改的话直接改配置文件,代码维护 起来就很方便了,同时有时候要适应某些需求,Java类里面不一定能直接调用另 外的方法,这时候也可以通过反射机制来实现。
注解(Annontation)是Java5引入的一种代码辅助工具,它的核心作用是对类、方法、变 量、参数和包进行标注,通过反射来访问这些标注信息,以此在运行时改变所注解对象的行为。
四、集合类,
zsgc_迭代器
JAVA容器
ArrayList底层数组实现,封装了常见的增删改查操作,并且支持动态扩容。适 合查找多的场合。
LinkedList基于链表实现的列表。适合增删情况较多的场合。
TreeSet,基于二叉排序树(红黑树)实现的。TreeSet里最典型的就是它用到 了两种排序方式,即基于元素对象自身的实现的Comparable接口的自然排序, 以及基于更为灵活不与单个元素绑定的Comparator接口的客户化排序。自己在 构造的时候传入一个比较器即可。
HashMap是用来存储键值对的映射关系,底层是用数组+链表实现的。结合put 操作讲一下。HashSet其实就是基于HashMap实现的,只不过将值固定为一个固定的值。
LinkedHashMap,支持按照插入顺序排序。
PriorityQueue优先级队列,一个基于优先级堆的无界优先级队列
动态代理为什么使用反射而不使用继承?
这个问题有坑啊,动态代理可以用继承和反射都可以实现。
JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用 InvokeHandler来处理。
CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象 类的class文件加载进来,通过修改其字节码生成子类来处理。
区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成 一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。
总结:
1.JDK代理使用的是反射机制实现aop的动态代理,CGLIB代理使用字节码处理框架asm, 通过修改字节码生成子类。所以jdk动态代理的方式创建代理对象效率较高,执行效率较 低,cglib创建效率较低,执行效率高;
2.JDK动态代理机制是委托机制,具体说动态实现接口类,在动态生成的实现类里面委托 hanlder去调用原始实现类方法,CGLIB则使用的继承机制,具体说被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋 值给接口。
两种动态代理方式及其区别(代理模式)
JDK的动态代理(依赖于接口)
- 在Java的动态代理机制中,有两个重要的类或接口,一个是InvocationHandler接 口,另一个是Proxy类。
- InvocationHandler接口是给动态代理类实现的,负责处理被代理对象的操作
- Proxy类是用来创建动态代理类实例对象的,只有得到这个对象,才能调用需要代 理的方法。
- 动态代理的代理类是在静态代理类上进行修改,将动态代理类实现 InvocationHandler接口,重写Invoke方法,Invoke方法通过传入的被代理类方法和 参数来执行。
JDK动态代理和Cglib动态代理的区别:
- JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
- Cglib因为是继承机制,所以无法代理被final修饰的方法。
- JDK和Cglib都是在运行期间生产字节码,JDK是直接写class字节码,Cglib使用 ASM框架写class字节码;cglib代理实现更复杂,生成代理类比JDK效率低。
- JDK调用代理方法,是通过反射实现机制调用,cglib是通过Fashclass机制直接调 用方法,效率更高。
Fastcalss机制:
为代理类和被代理类个生成一个class,这个class会为代理类或被代理类的方法分配一个 index。这个index当做一个入参,Fashclass就可以直接定位要调用的方法,并直接进行调用。这样 省去了反射调用,所以效率高。
五、JDBC:
桥梁:
1.加载驱动,
2.连库,
3.增删改查
六、IO流:
字节流
字符流