1、Java面向对象有哪些特征
Java最重要的三大特征为封装、继承和多态。
封装是指隐藏类的内部机制,在不影响正常使用的情况下,可以任意修改类的内部结构,这种方式一方面保护了内部数据,并且增加了代码的可维护性,便于修改。
继承是指从已有的类中派生出新的子类,子类可以保有父类的属性和行为,在此基础上可以继续更新,加入一些父类不具有的属性或方法。这种方式提高了代码的可扩展性和复用性。
多态,封装和继承最后会归结为多态,多态的三个要素是封装、继承和父类引用指向子类对象。多态指的是类与类之间的关系,两个类存在继承关系,存在方法的重写,因此在调用时有父类引用指向子类对象。增加了代码的可移植性,健壮性和灵活性。
Animal A = new Dog('A');
2、ArrayList和LinkedList的区别
这两个实现了List接口,但是他们的底层数据结构不同。ArrayList底层由数组实现,LinkedList底层由链表实现。
插入、删除数据时,LinkedList性能优于LinkedList;
访问数据时,Arraylist优于LinkedList。
底层实现,插入、删除、访问性能。
3、线程安全与不安全
假设一张卡里有1000块钱儿,两个人同时在不同的地方取同一张卡里的1000块钱,如果是线程不安全的,那么两人都能取出1000;线程安全下,只有一个人能取出1000。
线程安全就是当多个线程执行同一段代码时,通过加锁机制,使每次执行的结果和单线程执行结果一样,不存在执行结果的二义性。线程不安全就是不提供加锁机制保护,可能会出现多个线程先后改变数据结果的情况。
3、高并发中的集合有哪些
第一代线程安全集合类:Vector Hashtable,使用synchronized修饰方法,缺点是效率低下;
第二代线程非安全集合类:ArratList 和 HashMap,他们非线程安全但性能好,若要保证线程安全,则需要使用Collections.synchronizedList和Collections.synchronizedMap,通过代码块锁锁住代码。
第三代线程安全集合类:concurrent*,ConcurrentHashmap;CopyOnWriteArrayList类,底层使用Lock锁,保证安全和性能。
4、JDK1.8的新特性有哪些(需要补充)
1)接口的默认方法,1.8允许给接口添加非抽象的方法实现,只需要使用default关键字即可,这个特征又叫扩展方法。
2)Lambda表达式,简化编程
3)函数式接口,产生了新的接口,
5、抽象类和接口有哪些区别
相同点:
1、都不能被实例化
2、可以将抽象类和接口类型作为引用类型
3、一个类如果继承了某个抽象类或者实现了某个接口,则都需要对其中的抽象方法全部进行实现,否则该类仍然需要声明为抽象类
不同点:
1、抽象类中可以定义构造函数,接口中不能定义构造器;
2、抽象类中可以有抽象方法和具体方法,接口中方法全部为抽象方法;
3、抽象类中的成员可以是public、private、protect和默认;接口中的成员全部是public。
4、抽象类中可以定义成员变量,接口中定义的成员变量实际上都是常量;
5、抽象类中可以包含静态方法,接口中不能有静态方法;
6、一个类只可以继承一个抽象类,一个类可以实现多个接口。
什么时候用interface,什么时候用抽象类
抽象类主要用于描述概念,例如动物、植物等,这种在我们的意识中存在具体概念形象的时候,用抽象类;
当用于描述一类事物的共性特征时,用接口,例如会飞,会跑等
6、Hashcode和equals如何使用
其实主要问的就是HashMap的底层原理,我们往HashMap中放数据时,是一对一对地存放数据的,是参照key来存放数据的。
7、Java代理的几种实现方式
代理方式分为静态代理和动态代理。
静态代理只能静态的代理某些方法或者某些类,是在不改变目标对象的前提下,实现对目标对象的功能扩展;他实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都需要进行相应的修改,增加维护成本。
动态代理包含proxy代理和CGLIB动态代理。
Proxy代理是JDK内置的动态代理,特点是面向接口,对实现类在实现接口中定义的方法进行增强。靠反射机制实现,有局限性
CGLIB是面向父类的动态代理,需要导入第三方依赖,底层通过子类继承父类并重写的形式实现增强。应用更加广泛。
8、Java中的==和equals有哪些区别
都是用于判断两个值是否相等,然而两者一个是方法一个是运算符。
“==”:如果比较的是基本数据类型,那么比较的就是数值是否相等;如果比较的是引用数据类型,那么比较的就是对象的地址值是否相等。
“equal”:用来比较方法的两个对象是否相等,它不能用于基本数据类型,可以进行重写。
9、Java中的异常处理机制是什么
Java的异常处理由五个关键字实现:try、throw、throws、catch、finally。Java的异常处理机制分为声明异常、抛出异常和捕获异常。
声明异常——throws
抛出异常——throw
捕获异常——try,catch,finally
throw和throws的声明位置不同:throw声明在方法内部,throws声明在方法处。throw后面抛出的是具体的异常对象,throws由于声明在方法处,所以用来表明整个方法里可能会出现这种类型的异常。throw用于制造异常,throws用于告诉调用者可能出现这种异常,需要抛出或使用其他方式处理。
10、重写和重载有什么区别
重载(overload)是在位于同一个类中的,方法重载是方法的方法名相同,但方法的参数不同,方法体对应的内容也不同。
重写基于子类父类,子类对于父类中的一些方法不满意,在子类中进行方法重写(override),方法体不同。父类的修饰符权限要低于子类的,参数类型必须相同。
11、String、StringBuffer和StringBuilder的区别和使用场景
String是不可变字符串,其他两个是可变字符串。在地址不可变的情况下,具体值不能变。
StringBuffer底层是一个数组,内部有value和count两个参数,然后不停的追加,放不下以后会进行数组扩容。Stringbuffer线程安全,效率低,有synchronized的保证线程安全;stringBuilder线程不安全,效率高。
12、怎样声明一个类不会被继承、什么场景下会用
如果一个类被final修饰,那么就不可以有子类,不会被继承。比如Math类,它的构造器由private修饰,外部无法创建对象,他的所有方法都加有static,通过类名.方法进行调用。
13、自定义异常在生产中如何应用
系统中的一些错误符合Java语法,但不符合业务逻辑;
在分层的软件结构中,通常在表现层统一对其他层次的异常进行捕获处理。