目录
HashMap的底层是由数据+链表+红黑树(一种二叉查找树)。
JDK,JRE,JVM
-
- JDK:Java语言工具包,包括JRE与JVM
- JRE:Java运行环境,不包含开发环境
- JVM:Java虚拟机
- JVM整个类加载过程的步骤
- 装载:装载过程负责找到二进制字节码并加载至JVM中,JVM通过类名,类所在的包名通过ClassLoader来完成类的加载。同时用:类名+包名+ClassLoader实例ID来标记已装载的类
- 链接:链接过程负责对二进制字节码的格式进行校验,初始化装载类中的静态变量以及解析类中调用的接口,类。
完成校验后,JVM初始化类中的静态变量,并将其赋值为默认值。
-
-
- 初始化:初始化过程即为执行类中的静态初始化代码,构造器代码以及静态属性的初始化。
-
四种情况执行初始化:new,反射调用了类中的方法,子类调用了初始化,JVM启动过程中指定的初始化类。
-
- ClassLoader抽象类的几个关键方法
- LoadClass:负责加载指定名字的类,实现方法为先从已经加载的类中寻找,如没有则继续从parent ClassLoader中寻找,如果还没有找到,就从system中寻找。
- FindLoaderClass:此方法负责从当前classloader实例对象的缓存中寻找已加载的类,调用native的方法
- FindClass:此方法直接抛出ClassNotFindException,因此需要通过覆盖loadClass或自定义的方法加载相应的类
- findSystemClass:从system中寻找类,如未找到,则在Bootstrap ClassLoader中寻找,如仍未找到,返回null
- defineClass:此方法负责将二进制的字节码转换为Class对象
- resolveClass:此方法负责完成class对象的链接,如已链接过,则会直接返回。
- JVM运行时数据区:
- PC寄存器:PC寄存器是用于存储每个线程下一步将执行的JVM,指令,如该方法为native(本地)的,则PC寄存器中不存储任何信息。
- JVM栈:JVM栈是线程私有的,每个线程创建的同时,都会创建JVM栈,JVM栈中存放的为当前线程中局部基本类型的变量。部分的返回结果以及Stack Frame,非基本类型的对象在JVM栈上仅存放一个指向堆上的地址。
- 堆:他是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配,堆中的对象的内存需要等待GC进行回收。
- 方法区域:又被称为持久代。
- ClassLoader抽象类的几个关键方法
方法区域存放了所加载的类的信息(名称,修饰符),类中的静态变量,类中定义为final类型的常量,类中的field信息,类中的方法信息,当开发人员在程序中调用getName,等方法来获取信息时,这些数据都来源于方法区域,同时方法区域也是全局共享的,在一定的条件下它也会被GC,当方法区域需要使用的内存超过其允许的大小时,会抛出OutOfMemory的错误信息。
-
-
- 运行时常量池:存放的为分类中的固定的常量信息,方法和field的引用信息,其空间从方法区域中分配。
- 本地方法堆栈:JVM采用本地方法堆栈来支持native方法的执行,此区域用于存储每个native方法调用的状态
-
&与&&的区别:
&&称为短路与,如果前面条件为False,则不执行判断中的操作。
|与|| 与上类似
Override规则
子类可以覆盖父类的方法
要求:必须同名,同参,同返回值。
不能有比父类更严格的访问权限。
不能比父类中的方法抛出更多的异常。
Super关键字
可以访问父类的全局变量
可以访问到父类被重写的方法
可以访问父类的构造器
静态与单例
Static 静态资源,只编译一次。比类实例化要早。所以类的对象公用一个static对象或属性。
Singleton 单例模式,就是类只声明一个对象。是封装的一种表现,比静态的要好,可以继承与多态。举例如下:
String与StringBuffer的区别。
:StringBuffer代表一组可改变的Unicode字符序列。
String的值是不可改变的,如果进行赋值操作String a = "a",将会再生成一个新的String对象,存在新的内存地址中。大量的对String赋值会占用大量内存。
StringBuffer与StringBuilder的区别:
StringBuffer和StringBuilder功能基本类似,主要区别在于StringBuffer类的方法是多线程安全的,StringBuilder不是线程安全的,相比而言,StringBuilder会更快一点。
速度比较:一般情况下,速度从快到慢:StringBuilder>StringBuffer>String,这种比较是相对的,不是绝对的。
(1).如果要操作少量的数据用 = String
(2).单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
(3).多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
Collection(集合) API
由两个类继承Set 与List
Set:无序无重复集。List:有序可重复集。
HashMap的底层是由数据+链表+红黑树(一种二叉查找树)。
小于8,则是数组+链表,大于8则是数组+红黑树是为了避免拉链过程。
HashMap与HashTable与TreeMap的区别
HashTable:同步,开销大
HashMap:异步
TreeMap:基于红黑树提供的顺序访问的Map
Set:表示不重复的对象集合
-
- HashSet:无序的集,能够快速的查找到指定的对象。(散列码)
- TreeSet:有顺序的,无重复的集,会自动排序
数据库事物:
事物:事物是需要在同一处理单元中执行的一系列更新处理的集合(写在service层)
特点:原子性(Atomicity )、一致性( Consistency )、隔离性或独立性( Isolation)和持久性(Durabilily),简称就是ACID
Iterator:迭代器。负责遍历对象
-
- Boolean hashNext:如果遍历的集合还没有完,返回true
- Object next():返回集合里的下一个元素
- Void remove():删除集合中上一次next方法上一次返回的元素
异常
运行时异常:RuntimeRxception
ArithmeticException:数学计算异常
NullPointException:空指针异常
NegativeArraySizeException:负数组长度异常
ArrayOutOfBoundsException:数组索引越界
ClassNotFoundException:类文件未找到异常
ClassCastException:造型异常
非运行时异常:IOException
FileNotFoundException:文件未找到异常
EOFExeption:读写文件尾异常
MalformedURLException:URL格式错误异常
SocketException:Socket异常
IO输入与输出
分为两类InputStream
OutputStream
Java线程
-
- 方法一:
- 创建线程:定义一个线程类,继承类Thread并重写其中的方法run(),run()称为线程体。
- 注解:由于java只支持单继承,用这种方法定义的类不能再继承其他类。
- 方法二:
- 提供一个实现接口Runnable的类作为线程的目标对象,在初始化一个Thread类或者Thread子类的线程对象时,把目标对象传递给这个线程实例,又该目标对象提供线程体。
- 线程的状态
- 方法一:
创建状态:新建线程对象
可运行状态:调用start方法
不可运行状态:sleep方法,线程阻塞
终止状态:自然撤销,强制停止stop
线程控制: 查看是否处于运行状态(Runnable)isAlive()
中断线程(不是终止)Thread.sleep()或则Thread.yield()
设置线程优先级getPriority()
-
- 并发问题:
- Synchronized(),同步监视器。
- 并发问题:
网络编程(socket编程)
主要用ServerSocket实现。用于侦听一个客户端的Socket连接,如果没有连接,他将一直等待(写在服务器端)
Socket类,写在客户端
反射机制
只要给定类名,即可通过反射获取类的所有属性。
反射可以在程序运行时获取任意一个对象所属的类对象。
在运行时可以获取到类中所有属性对象,并对其进行操作,包括私有属性。
在运行时可以获取到类中,父类中所有方法,并调用。
目前主流的应用框架如Struts2,Hibernate,Spring,SpringMVC等框架,全部是利用Java的反射机制来实现的。
类的实现机制
-
- 通过路径与文件名,实现类
- Class cl1 = null;
- cl1 = Class.forName(path)
- 通过实例化对象 new个对象
- 通过class直接获取对象
- cl3 = 类目.getClass();
- 再通过newInstance()实例化对象。
- 通过路径与文件名,实现类
Field对象的机制与实现(操作属性)
-
- 用于表示类中,接口中属性对象的类。
- 可以操作类中私有,以及公有等全部属性的信息。
- 用法:
- Field[] field = class.getDeclaredFields () //可以获取到私有属性
- Field[] field = class.getFields() //不可以获取到私有属性
- 获得具体对象的属性与值
没有field.setAccessibe(true),会报错,这句话开启访问权限
Method对象ss的机制与实现(操作方法)
-
- Method类是用于表示类中,接口中方法对象的类
- 用法与Field非常相似
单链表与环的问题
- 判断单链表中是否有环
- 建立两个指针,你个快指针(fast)一个慢指针(slow)。当存在环时,肯定是快指针先入环,然后两个指针的距离慢慢减小,当到0时两个指针相遇。存在环。
数据库基础
-
- 一个列的长度不能超过16kb,列数不能多余1017
- 与orcale不同自动提交命令。
JDBC存储过程的调用
无参数的存储过程:
CallableStatement c = conn1.prepareCall(“call SecletUser()”);
c.execute();
ResultSet res = c.getResultSet();
输入参数的存储过程:
CallableStatement c = conn1.prepareCall(“call selectUserBId(?)”)
c.setString(1,id);
c.execute();
ResultSet res = c.getResultSet();
输出参数的存储过程:
CallableStatement c = conn1.prepareCall(“call selectUserBId(?)”)
c.registerOutParameter(1,Types.INTEGER)
c.execute();
Integer res = c.getInt(1);
番外:设计模式
- 开篇:总共有23种设计模式,按类型可分为三类
- 创建型:
-
- 抽象工厂模式
- 工厂方法
- 建造者模式
- 原型模式
- 单例模式
-
- 构造型模式:
-
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 桥接模式
- 组合模式
- 享元模式
-
- 行为型模式
-
- 策略模式
- 模板方法模式
- 观察者模式
- 迭代子模式
- 责任链模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式
-
- 创建型:
如果分两种,可分为并发型模式与线程池模式
- 设计模式的六大原则
- 总原则:开闭原则
- 对内开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想达到这样的效果,我们需要使用接口和抽象类。
- 单一职责原则
- 不要存在多于一个导致类变更的原因。
- 里氏替换原则
- 里氏替换原则(LSP)是面向对象设计的基本原则之一。任何基类可以出现的地方,子类一定可以出现。LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才可以真正被复用,而衍生类也能够在基类的基础上增加新的行为。
- 子类对父类的方法尽量不要重写和重载,因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。
- 依赖倒转原则
- 这是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
- 接口隔离原则
- 每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分
- 迪米特法则(最少知道原则)
- 一个类对自己依赖的类知道的越少越好,也就是说无论被依赖的类多复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。
- 合成复用原则
- 尽量首先使用合成/聚合的方式,而不是使用继承。
- 总原则:开闭原则