Java基础
Object类详解
Object类的几个重要方法
- toString
- equals: 对于Object类的equals()方法来说,它是判断调用equals()方法的引用与传进来的引用是否一致,即这两个引指向的同对象。 对于 Object类的equals()方 法来说,它等价于 == 。 关于Object类的equals方法的特点 a) 自反性:x.equals(x)应该返回true b) 对称性:x.equals(y)为true,那么y.equals(x)也为true c) 传递性:x.equals(y)为 true并且y.equals(z)为true,那么x.equals(z)也应该为true d) 一致性:x.equals(y)的第一次调用为true,那么x.equals(y)的第二次、第三次、第n次调用也应该为true,前提条件是在比较之间没有修改x也没有修改y e) 对于非空引用x,x.equals(null)返回false
- hashCode:Object类的hashCode值表示的是对象的地址 关于Object类的hashCode()方法的特点: a) 在Java应用的一次执行过程当中,对于同一个对象的hashCode方法的多次调用,他们应该返回同样的值(前提是该对象的信息没有发生变化) b) 对于两个对象来说,如果使用equals方法比较返回true,那么这两个对象的hashCode值一定是相同的 c) 对于两个对象来说,如果使用equals方法比较返回false,那么这两个对象的hashCode值不要求一定不同(可以相同,可以不同),但是如果不同则可以提高应用的性能 d) 对于Object类来说,不同的Object对象的hashCode值是不同的(Object类的hashCode值表示的是对象的地址) 如果我们重写equals方法,那么也要重写hashCode方法,反之亦然
- getClass
ISSUE: Object类方法相关问题
ISSUE: equals方法的意义
对于object对象来说,他的equals方法是判断调用equals()方法的引用与传进来的引用是否一致,即这两个引指向的同对象。 而对于其他类,如果重写了equals方法,则按照具体方法实现判断内容是否一样
String类源码
- equals方法重写:对于String类的equals()方法来说,它是判断当前字符串与传进的内容 是否一致
- 是final类,不能被继承
- String 是常量,其对象一旦创建完毕就无法改变。当使用+拼接字符串时,会生成新的String对象,而不是向原有的String 对象追加内容
- String Pool(字符串池,池用于提高效率)栈 String str = 'aaa'(字面方式赋值) 和String str = new String("aaa")的差别
- intern()方法
- StringBuffer
集合源码
- java.util包
- 集合框架中的接口
Collection interface
集合框架
ArrayList
- 底层就是 Object[] elementData的数组,使用不带参数的构造方式生成一个ArrayList时,默认生成长度为10的Object数组
- add操作: 如果增加的元素个数超过了10个,那么ArrayList底层会新生成一个数组,长度为原数组的1.5倍+1,然后将原数组的内容复制到新数组当中,并且后续增加的内容都会放到新数组当中。当新数组无法容纳增加的元素时,重复该过程
- remove操作:对于ArrayList元素的删除操作,需要将被删除元素的后续元素向前移动,涉及到大量元素的移动,代价比较高
LinkedList
LinkedList中所维护的是一个个的Entry对象
HashSet
返回无序set。当使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hashcode值是否与增加的对象的hashCode值一致; 如果不一致,直接加进去; 如果一致,再进行equals方法的比较,equals方法如果返回true,表示对象已经加进去了,就不会再增加新的对象,否则加进去。
底层原理:HashSet的底层是HashMap 当使用add方法将对象添加到Set当中时,实际上是将该对象作为底层所维护的Map对象的key,而value则都是同一个Object对象(该对象我们用不上)
TreeSet (SortedSet接口的实现)
返回排序后的set。 底层有比较机制, 对象需要指定好排序规则,实现Comparator接口
HashMap
底层原理: HashMap底层维护一个数组 ,我们向HashMap中所放置的对象实际上是存储在该数组当中, 实际是 数组+链表的混合结合实现 数组的初始长度(16), 负载因子(0.75)[当数组容量有75%被占用了,数组就会扩容两倍 ]。
当向HashMap中put一对键值时,它会根据key的hashCode值计算出一个位置,该位置就是此对象准备往数组中存放的位置。如果该位置没有对象存在,就将此对象直接放进数组当中;如果该位置已经有对象存在了,则顺着此存在的对象的链开始寻找(Entry类有一个Entry类型的next成员变量,指向了该对象的下一个对象),如果此链上有对象的话,再去使用equals方法进行比较,如果对此链上的某个对象的equals方法比较为false,则将该对象放到数组当中,然后将数组中该位置以前存在的那个对象链接到此对象的后面。
TreeMap
ISSUE: ArrayList与LinkedList的比较分析
- ArrayList底层采用数组实现,LinkedList底层采用双向链表实现
- 当执行插入或者删除操作时,采用LinkedList比较好
- 当执行搜索操作时,采用ArrayList比较好
- 当向ArrayList添加一个对象时,实际上就是将该对象放置到了ArrayList底层所维护的数组当中;当向LinkedList中添加一个对象时,实际上LinkedList内部会生成一个Entry对象,该Entry对象的结构为
{
Entry previous;
Object element;
Entry next;
}
其中的Object类型的元素element就是我们向LinkedList中所添加的元素,然后Entry又构造好了向前与向后的引用previous、next,最后将生成的这个Entry对象加入到了链表当中。换句话说,LinkedList中所维护的是一个个的Entry对象
ISSUE: Vector, Hashtable的特征
自动装箱与自动拆箱
Integer 源码
方法valueOf:-128~127 会被缓存, 范围在此的数值不会生成新的对象, 比Integer的构造方法性能更好(构造方法生成的数据一定是生成新对象的)
反射 reflection
I/O
字节流和字符流
字节流
核心抽象方法:read(), write()
- InputStream Interface, OutputStream Interface(接口):
- 用于操作文件的方法FileInputStream, FileOutputStream
- ByteArrayInputSream(byte[] byteArray, ..), ByteArrayOutputStream
字符流 支持Unicode字符
- Reader和Writer抽象类
- InputStreamReader和OutputStreamWriter 字节流和字符流的桥梁
节点流和过滤流
过滤流 FilterInputStream, FilterOutputStream
过滤流会将文本数据处理转成二进制流
- BufferedInputStream, BufferedOutputStream, ** 包装输入流和输出流**
序列化
将对象转换成字节流保存起来,并在以后还原这个对象,这种机制叫做对象序列化,实现对象持久化
需要实现Serializable接口(标示性接口)
- 序列化只保存对象的非静态成员变量
- 如果一个对象的成员变量也是一个对象,这个对象也会被保存
- 如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作都会失败(处理方法!!! 将这个引用标记为transient)
- static变量无法序列化
常用设计模式
单例模式
策略模式(实例:TreeSet,TreeMap)
- 抽象策略角色
- 具体策略角色
- 环境角色
策略模式的编写步骤:
- 对策略对象定义一个公共接口
- 编写策略类,该类实现了上面的公共接口
- 在使用策略对象的类中保存一个对策略对象的引用
- 在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值。 缺点: 1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类 2.造成很多的策略类;解决办法:采用工厂方法
代理模式
为其他对象提供一种代理以控制对这个对象的访问
代理对象:在客户端和目标对象之前起到中介作用
- 抽象角色:真是对象和代理对象的共同接口
- 代理角色:还有对真实对象的引用,从而可以操作真是对象
- 真实角色:代理角色表达的真实对象
静态代理的缺点:类的急剧膨胀,如果事先不知道真实角色,也不能用
动态代理: 运行是时候生成类,在生成类的时候提供一组interface,然后该class就宣称实现了这些Interface
Interface InvocationHandler (调用处理器) 一个invoke方法:返回object
Object invoke(Object proxy,
Method method,
Object[] args)
Proxy
public static Object newProxyInstance(ClassLoader loader,
Class[] interfaces,
InvocationHandler h)
通过动态代理,被代理的对象可以在运行时动态改变,需要控制的接口可以在运行时改变,控制的方式也可以改变,从而实现了非常灵活的动态代理关系
观察者模式(实例:AWT事件模型)
定义一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有的观察者对象,让他们自动更新自己
-抽象主题角色
-抽象观察者角色
-具体主题角色
-具体观察者角色
JDK内置支持 Observable类
装饰模式(实例:I/O)
又名包装模式,以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
可以在不创造更多子类的情况下,将对象的功能加以扩展
- 抽象构建角色 Component
- 具体构建角色 Concrete Component
- 装饰角色 Decorator
- 具体装饰角色 Concrete Decorator
其中 装饰角色持有一个构建对象的引用,并定义一个与抽象构建接口一致的接口
工厂方法
迭代器模式
异常
异常分类: Checked Exception(非Runtime Exception) Unchecked Exception(Runtime Exception)
运行时异常都是继承RuntimeException的
System.exit(0) 会终止运行的虚拟机
内部类
分类:静态内部类,成员内部类,匿名内部类(隐式的继承了一个父类或者实现了一个接口), 局部内部类
线程及并发基础
ISSUE: 线程与进程的区别
- 多个进程的内部数据和状态是完全独立的,而多线程是共享一块内存空间和一组系统资源,有可能相互影响。
- 线程本身的数据通常只有寄存器数据,以及
- 进程是重量级的任务,需要分配独立地址空间。而
常见面试题汇总
- transient 仅用在序列化,瞬时,使用以后就被修饰的数据就不会序列化到文件中
- volitail
reference
https://blog.csdn.net/as6757uyy65uy75/article/details/79370686