Q1面向对象
类、对象特征?
类:对事物逻辑算法或概念的抽象,描述一类对象的行为和状态。
OOP三大特征,封装,继承,多态
封装:隐藏属性实现细节,只公开接口。将抽象的数据和行为结合,形成类。目的是简化编程,提高安全性。
继承:关键字extends, is-a关系,子类拥有父类的属性和方法,子类可重写override父类同名方法, 实现子类特性,单继承。构造方法,静态方法,没有访问权限不能继承。
优点:抽取共同为基类,提高复用率。缺点:增加了耦合性,改变父类影响子类。
Java多态的理解?实现的必要条件?实现方式?
多态:对同一个消息根据发送对象不同产生不同的行为。
三个条件:继承,重写,向上转型(父类引用指向子类对象)
实现方式:编译时多态:重载overload(同一个类):通过参数列表不同区分不同方法
运行时多态:1.子类继承父类进行方法重写 2. 通过实现接口并覆盖接口同一方法(面向接口编程)
优点:降低耦合,可替换,可扩展
什么是内部类?为什么要使用内部类?成员内部类,静态内部类,局部内部类和匿名内部类的理解和作用,以及应用场景?
内部类:将一个类的定义放在另一个类的定义内部。
为什么要用:能独立继承接口实现,解决多重继承问题,实现回调(适用于事件驱动架构)
特性:创建内部类不依赖外部类的创建;成员内部类可以无条件访问外部类的所有属性和方法 (一个外部类this指针);
除了外部类,其他类不能直接访问内部类;
内部类可以private修饰,修饰后外部类之外不可见。
成员内部类:只能通过外部类对象创建内部类对象: Outer.Inner inner = new Outer().new Inner();
其他类不能直接使用该内部类,不能有static变量和方法
经典场景: 排序比较器 new Comparator<Person>(){ … }
局部内部类:创建一个类辅助解决方案,但不希望公开,仅仅为外部类某个方法中使用。
不能有public、protected、private及static修饰符。
局部内部类只能访问方法中声明的final类型的变量。
场景很少。。
匿名内部类:没有构造器的类。匿名内部类是直接使用new来生成一个对象的引用。
场景:大部分匿名内部类用于接口回调。
特性:没有访问修饰符;当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final;
场景:用于集成其他类或者实现接口,并不需要增加额外的方法,只是对集成方法的实现或是重写。
静态内部类:使用Static修饰的内部类,也叫嵌套内部类。
可以直接创建实例不需要依赖外部类,只能访问外部类静态成员变量和方法
静态内部类使用的形参为何要为final?
拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。
如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。
闭包和内部类的区别?
闭包的概念产生于函数式编程中,在函数式编程中,函数是第一等公民,这也就意味着,你可以将函数当做参数或是返回结果。
闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)
闭包从底层理解,就是函数本身和其所需外部变量的引用,创建过程是capture by reference。
Java不能显示的支持闭包,通过“接口+内部类”来实现。
Java在实现匿名内部类对外部局部变量访问时,是对局部变量创建值拷贝,然后供匿名内部类来使用。不像Go编译器将局部变量提升到堆中,然后传递引用。
Java中匿名内部类是一个不完整的闭包,是capture by value, 而不是 capture by reference。
重载Overload和重写Override的区别?
重载overload(同一个类):通过参数列表不同区分不同方法
重写(override)(子类继承父类):子类中对父类同名方法进行重新定义
静态属性和静态方法是否可以被继承,重写?为什么?
java 静态方法,静态属性属于静态绑定,声明为父类就访问父类的父类的静态方法,静态属性,声明为子类,就访问子类,如果子类不存在该静态方法,静态属性,就访问相应父类的。
重写的功能是:"重写"后子类的优先级要高于父类的优先级,针对多态的概念。
抽象类和接口的定义,区别,作用,应用场景?
抽象类:包含抽象方法的类。is-a, abstract关键字 ,类继承抽象类extends, 抽象方法:abstract修饰方法,只有声明没有实现。含有抽象方法就是抽象类。
子类继续抽象类则必须实现抽象类的抽象方法。
作用是为了将来对该类进行扩展。
接口:对行为的抽象。has-a, interface关键字,类实现接口implement, 方法会被隐式地指定为public abstract方法。
区别:1. 成员变量类型。接口中的成员变量只能是public static final类型的。
2. 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法。
3. 接口中不能含有静态代码块以及静态方法(Java8中允许我们在接口中定义默认方法和静态方法),而抽象类可以有静态代码块和静态方法。
4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
5. 抽象类继承是一个 "是不是"的关系,而 接口实现则是 "有没有"的关系。
对象克隆的方式几种?
1. 将A对象的值分别通过set方法加入B对象中
2. 通过重写java.lang.Object类中的方法clone()
3. 通过org.apache.commons中的工具类BeanUtils和PropertyUtils进行对象复制。BeanUtils.copyProperties(stu2, stu1);
4. 通过序列化实现对象的复制:
把源对象写入到一个字节流中,再从字节流中将其读出来,这样就可以创建一个新的对象了,并且该新对象与母对象之间并不存在引用共享的问题,真正实现对象的深拷贝
浅拷贝和深拷贝区别?
浅拷贝:基本数据类型,对值进行新的拷贝;引用数据类型(类,接口,数组)只复制引用。引用的另一处修改,当前对象也会被修改。
对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象
深拷贝:把要复制的对象所引用的对象都复制了一遍。
Q2基本数据类型
基本数据类型各占多少字节?
byte 1字节(8位) short 2字节(16位) char 2字节(16位) int 4字符(32位) long 8字节(64位) float 4字符(32位) double 8字节(64位) Boolean 1字节(8位)
Q3关键字
Java中==和equals的区别?
==是内存地址的比较
Equals是Object的方法,比较对象是否相等。默认equals是等价于==。通常重写equals,判断两个对象内容是否相等。
equals, hashCode的作用,联系?
Equals,不重写,判断两个对象内存地址是否相等。重写,判断两个对象的值是否相等。
HashCode()是Object里方法,获取哈希码(散列码),返回一个int整数。进而确定该对象在散列表中的位置。仅适用于集合中本质是散列表的类,如HashMap, HashSet, Hashtable.
关系:1. 不是散列表类,没关系。
2.散列表类:equals()相等,hashCode()一定相等。
如果两个对象hashCode()相等,它们并不一定相等。“两个不同的键值对,哈希值相等”,这就是哈希冲突。
Final关键字有哪些用法?
修饰的类不能被继承,修饰的方法不能被继承类重写。
常与Static一起,作为常量。
好处:1. 提高性能,JVM缓存final变量。2. 多线程下进行共享,不需要额外同步开销。
Final, finally, finalize的区别?
Final同上,finally是异常处理关键字,finalize是Object中定义的方法,在垃圾回收之前被JVM调用的方法。
Q4常用类
String, StringBuffer, StringBuilder区别? 底层原理?
1)String字符串常量,声明为final class,一旦创建不可变, Java对String操作是创建新对象,回收旧对象的过程。除了hash属性,其他属性都声明为final。如果拼接字符串会产生很多无用中间对象,影响性能。
2)StringBuffer字符串变量,对象是变量,可以改变。为解决大量拼接字符串产生中间对象问题而提供的类。Append方法追加字符串。
线程安全,所有修改数据方法都加synchronized。保证线程安全付出性能代价。
3)StringBuilder. JDK1.5发布,不需要线程安全的拼接字符串操作类,与StringBuffer没有区别,去掉了保证线程安全部分,减少了开销。
实现字符串反转有哪些方法?哪种效率最高?
1. 调用String的reverse()方法
2. 放入字符数组2分法+交换字符(冒泡对调) – 效率最高
3. 2分法+异或算法
4. 逆循环,用+拼接字符
5.使用堆栈,先进后出
6. Collections.reverse() 反转Character List.
7. Byte[]数组
思维导图Github: