1.面向对象
Java的面向对象包括封装,继承,多态
封装:说明一个类行为和属性与其他类的关系,低耦合,高内聚;
继承:是父类和子类的关系;
多态:说的是类与类的关系。
继承需要extends关键字,父类被private修饰的方法不能被继承。
2.ArrayList和LinkdeList的区别
ArrayList | LinkedList |
---|---|
底层是数组,可以以时间复杂度为O(1)的速度对元素进行随机访问 | 底层是链表,查阅复杂度为O(n), |
插入删除时不需要更新索引速度比较快 | 插入删除时需要更新索引(插入数组尾部时不需要),重新计算数组大小速度较慢 |
3.高并发中的集合有哪些问题?
集合类型 | 特点 | 缺点 |
---|---|---|
Vector,HashTable | 使用syncchronized修饰方法,默认线程安全 | 效率低下 |
ArrayList,HashMap | 用来代替Vector,HashTable,需要线程安全时,可以使用Collections.syncchronizedList(list);Collections.syncchronizedMap(map);(底层也是使用了syncchronized代码块锁,但是是锁在方法里) | 线程不安全 |
Java.util.concurrent.* ConcurrentHashMap CopyOnWriteArrayList CopyOnWriteArraySet | 底层大都采用Lock锁(1.8的ConcurrentHashMap不使用Lock锁),保证安全的同时,性能也很高 |
4.JDK8有什么新特新性
4.1Data Time API
LocalData, LocaTime, LocalDataTime, 这些新的日期API都是不可变的,而LocalData和LocalTime和最基本的String一样,是不变类型,线程安全,不能修改。
Data和simpleDataFormat都不是线程安全的
4.2 Lambda表达式
可以将函数作为参数,传入方法
Lambda表达式的使用前提
①、有一个接口
②、接口中有且仅有一个抽象方法
4.3 方法引用
4.4 Stream流API
4.5 HashMap的底层优化
4.6 default关键字
JDK8以后,接口里不仅仅只能有抽象方法,还能有default关键字修饰的默认方法
4.7 Optiona类
解决空指针问题
5 Java接口和抽象类有什么区别?
接口 | 抽象类 | |
---|---|---|
相同点 | 都不能够实例化, 都可以作为引用类型,一个类如果继承某个抽象类或者实现了某个接口都需要对其中的抽象方法进行全部实现,否则该类仍然需要被声明为抽象类 | |
不同点 | 接口中不可以定义构造器 | 抽象类中可以定义构造器 |
只可以有抽象方法 | 可以有抽象方法和具体方法 | |
接口中的成员都是public的 | 可以是private,默认,protected,public | |
接口中定义的成员变量其实都是常量 | 抽象类里可以定义常量 | |
接口中不能有静态方法 | 抽象类中可以有静态方法 | |
一个类可以实现多个接口 | 一个类只能继承一个抽象类 |
有抽象方法的类必须声明为抽象类,而抽象类未必有抽象方法
6 equals()和hashcode如何使用?
equals()方法源于java.lang.Object, 该方法用来验证两个对象的相等性
hashcode()方法也源于java.lang.Obiect,该方法用于获取给定对象的唯一的整数。当对象需要储存在哈希表这样的结构中时,可以用来确定他们的位置,HashTable,HashMap和HashSet使用的就是hashcode(),默认返回对象的内存地址值,HashMap底层在添加一个元素是就会计算每一个key的哈希值,当哈希值一样的话,会用equals()比较,判断key是否相同。 如果相同,则将覆盖对应的value;不相同才使用新的“桶”。
如果两个对象相等(equals()方法返回true),那么他们的hashcode()一定相等。如果hashcode()相等,他们不一定相同。
重写了equals(),必须要重写hashcode()
7 Java代理的几种的实现方式
代理模式:即通过一种对象来扩展目标对象,实现在不改变目标对象的基础上,为目标对象添加新的功能。
静态代理 | Proxy代理(jdk动态代理) | CGLIB代理 | |
---|---|---|---|
特点 | 只能静态的代理某些类或者某些方法,不推荐使用 | 面向接口的,不需要导入第三方依赖,可以对多种不同的接口进行增强,通过反射读取注解时,只能读取到接口上的注解 | 当某个类没有实现任何接口的时候,无法使用JDK动态代理,那么可以使用cglib进行代理 |
定义 | 使代理实现要代理的接口,并在内部定义一个私有化的接口变量, | 面向接口,只能对实现类在实现接口中定义的方法进行增强 | |
优点 | 不更改接口原有方法的情况下,对功能进行扩展 | 当接口需要变更时我们代理工厂无需变更 | |
缺点 | 随着接口功能的增加,代理类也需要维护 | 要代理的目标并没有实现任何接口,无法使用该代理 |
AOP的源码中同时用到了这两个动态代理方式,JDK动态代理是由java内部的反射机制来实现的,CGLIB是通过继承来实现的,底层时通过asm(Java字节码操控框架)来实现的(采用字节码的方式,给A类创建一个子类B,子类的方法拦截技术拦截所有的方法调用)。
总提来说,反射在生成代理类时比较高效,而asm是在生成类之后的相关执行过程比较高效(可以通过将asm生成类进行缓存解决asm生成类过程低效的问题)。
8 ==和equals的区别
- 一个是运算符一个是方法
- ==比较的是基础类型的话,比较的是值是否相等,比较引用类型的话比较的是他们的地址值是否相等。
equals比较的内容是否相等 - 如果没有重写equals的话,就是比较他们的地址值是否相等
9 Java的异常处理机制
Java的异常处理是通过5个关键字来实现的声明异常(throws),抛出异常(throw)和捕获异常(try、catch、finally)
Java通过面向对象的方法进行异常处理,一旦方法抛出异常,系统会自动根据异常对象寻找合适的异常处理器(Exception Handler)来处理该异常,把各种异常进行分类,并提供了良好的接口。在Java中,每个异常都是一个对象,他是Throw类或者其子类的实例。
throw和throws的区别:
throw | throws | |
---|---|---|
位置不同 | 在方法内部 | 在方法的签名处,方法的生命处 |
内容不同 | throw+异常对象(检查异常,运行时异常) | throws+异常的类型(可以是多个类型) |
作用不同 | 异常出现的源头,制造异常 | 在方法声明处,告诉调用者,此方法可能会出现这类的异常,然后调用者要么自己处理,要么继续上抛 |
10 重载和重写的区别
重载发生在一个类中,方法名相同,参数列表不同
重写发生在子类与父类之间,方法名必须相同,参数必须相同,方法体不同,返回值类型一致,父类的权限修饰符要低于子类
构造方法不能被重写,声明为final的方法不能被重写,声明static的方法不能被重写,但能再次声明。