2 语言基础 2
Java 技术体系
Java 核心本质在于 MVC 设计模式
JSP、Servlet 是技术的实现本质
本质技术:
JSP、HTML、CSS、JavaScript
前端 UI 设计 (HTML、CSS)
前端工程师 ( js 动态效果)
WEB 工程师(JSP、PHP、Node.JS)
控制层 前端 web 开发
业务层 只考虑操作本质
第一阶段 基础阶段
- SQL 语句:查询、更新、建表、约束
- Java 基础:基础语法、面向对象、类库、类集、IO、JDBC、DAO、设计模式
- JSP 开发:JSP、DAO、MVC(EL、JSTL)
总结:单表 CURD + 分页 + 上传
重复代码设计
观察问题的两个点:时间复杂度、空间复杂度
第二阶段 中级开发阶段
主要针对代码设计进行完善
- 性能:AJAX
- XML 与 DOM 解析、JSON
- jQuery、Jsonp
- GIT、SVN、Maven
第三阶段 框架开发
控制层、业务层、数据层改善
- Struts2:控制器、拦截器、实现原理
- Hibernate: 解决数据层开发设计,单表 CURD、一对多、多对多。缓存,设计思想、缺陷
- Spring IOC 与 AOP, SHH 整合
- MyBatis 好处,与 Hibernate 区别
- SpringMVC 与 Struts2 实现区别
- SpringMVC + MyBatis 开发与整合
多线程工具类
多线程同步处理
synchronized
JDK>=1.5 引入了
java.util.concurrent
package demo; import java.util.concurrent.locks.ReentrantLock; class MyTask { private static final ReentrantLock lock = new ReentrantLock(); private static int count = 0; public void doing() { lock.lock(); count ++; try{ System.out.println(Thread.currentThread().getName() + " " + count); }finally { lock.unlock(); } } } public class LockDemo { public static void main(String[] args) { for(int i=0; i<10; i++){ new Thread(()->{ new MyTask().doing(); }).start(); } } }
输出结果
Thread-0 1 Thread-9 2 Thread-3 3 Thread-2 4 Thread-5 5 Thread-7 6 Thread-4 7 Thread-6 8 Thread-8 9 Thread-1 10
反射参数
class
getClass()
反射与 new 的关系
package demo; interface IMessage{ void print(); } class MyMessage implements IMessage{ @Override public void print() { System.out.println("MyMessage"); } } public class reflectDemo { public static void main(String[] args) throws Exception { // 相当于 IMessage message = new MyMessage(); Class<?> clazz = Class.forName("demo.MyMessage"); IMessage message = (IMessage)clazz.newInstance(); clazz.getMethod("print").invoke(message); } }
方法变量与同步
方法中的变量是局部作用域,同步只考虑类属性
1、synchronized 同步方法
package demo; class MyThread implements Runnable { private int count = 5; @Override public synchronized void run() { System.out.println(Thread.currentThread().getName() + " " + this.count--); } } public class SyncDemo { public static void main(String[] args) { MyThread t = new MyThread(); for (int i = 0; i < 5; i++) { new Thread(t).start(); } } }
输出结果
Thread-0 5 Thread-2 4 Thread-1 3 Thread-4 2 Thread-3 1
2、不同步
package demo; class MyThread implements Runnable { private int count = 5; @Override public void run() { System.out.println(Thread.currentThread().getName() + " " + this.count--); } } public class SyncDemo { public static void main(String[] args) { MyThread t = new MyThread(); for (int i = 0; i < 5; i++) { new Thread(t).start(); } } }
输出结果
Thread-0 5 Thread-3 2 Thread-2 3 Thread-1 4 Thread-4 1
高并发包
java.util.concurrent
四种线程池
- 任意扩展的线程池
- 定长线程池
- 线程调度池
- 单线程池
接口特点:
不同子类对同一方法有不同的实现
- Hashtable 线程安全,一个时刻只允许一个线程访问
- HashMap 所有方法都是异步处理,非线程安全,访问速度快
- ConcurrentHashMap 可并发、高速访问
进程间通讯
进程间通讯:不同进程之间的 JVM 通讯
可以使用公共文件,或者直接进行管道流处理
进程和线程
进程执行速度慢
线程执行速度快
线程收到进程控制
集合信息
List 优先使用 get() 方法获取元素
接口标准
标准指的是所有类都要奉行的法则
接口的使用
- 接口:核心意义是暴露远程结构(方法视图)
- 抽象类:给接口和子类之间做过过渡使用
链表
内部类特点:
内部类可以方便的与外部类之间进行私有属性声明
内部类如果使用了 priate 声明,那么外部将无法直接使用它
外部类形式
class Link{} class Node{}
内部类形式
class Link{ private class Node{} }
线程池
无限大小的线程池
package demo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolDemo { public static void main(String[] args) { // 创建一个无限大小的线程池 ExecutorService service = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int temp = i; service.execute(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + temp); } }); } } }
固定个大小的线程池
package demo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolDemo { public static void main(String[] args) { // 创建一个3个大小的线程池 ExecutorService service = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int temp = i; service.execute(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + " " + temp); } }); } } }
取得可用线程池大小
Runtime.getRuntime().availableProcessors()
线程同步工具类
CountDownLatch 等待所有人都走了,我再干;一计到底,不可以重置
CyclicBarrier 汇聚多个等待线程,都到了,一起干,可以重置
不使用等待线程
package demo; public class ThreadPoolDemo { public static void main(String[] args) { for (int i = 0; i < 3; i++) { final int temp = i; new Thread(() -> { System.out.println(Thread.currentThread().getName() + " " + temp); } ).start(); } System.out.println("主线程执行"); } }
执行结果
主线程执行 Thread-2 2 Thread-0 0 Thread-1 1
使用 CountDownLatch
package demo; import java.util.concurrent.CountDownLatch; public class ThreadPoolDemo { public static void main(String[] args) throws InterruptedException { // 3个线程执行完后再继续 CountDownLatch countDownLatch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { final int temp = i; new Thread(() -> { System.out.println(Thread.currentThread().getName() + " " + temp); // 执行完成1次 countDownLatch.countDown(); } ).start(); } // 阻塞主线程执行 countDownLatch.await(); System.out.println("主线程执行"); } }
执行结果
Thread-0 0 Thread-2 2 Thread-1 1 主线程执行
使用 CyclicBarrier
package demo; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; public class ThreadPoolDemo { public static void main(String[] args) { CyclicBarrier cyclicBarrier = new CyclicBarrier(2); for (int i = 0; i < 3; i++) { new Thread(() -> { System.out.println(Thread.currentThread().getName() + "[before]"); try { cyclicBarrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "[after]"); } ).start(); } } }
执行结果
Thread-0[before] Thread-2[before] Thread-1[before] Thread-2[after] Thread-0[after] (线程卡主了)
基本类型与包装类型
JDK1.5 之后提供了自动装箱拆箱处理机制
- 包装类以对象的形式运行
- 包装类可以进行 null 的描述
- 基本数据类型型默认值是对应默认值,包装类默认值是 null
- 对象内容类 ov 都会使用包装类,便于 null 的控制
基本类型与引用传递
Java 中两种数据类型:
- 引用类型: 可以发生引用传递
- 基本类型: 只是一个值拷贝
包装类提供了 null
Mybatis 等使用包装类替代基本数据类型
使用 Object 作为接收参数
使用泛型来避免向下转型的操作
尽量减少 Object 使用
转型
向下转型:(不推荐)可以达到参数的统一,需要强制处理,造成类型不匹配
向上转型:最顶端是 Object
package demo; public class StringTest { public static void main(String[] args) { String str = "Hello"; // 向上转型 Object obj = str; // 向下转型 String ref = (String) obj; } }
引用传递
引用传递本质:
同一块堆内存能够被不同的栈内存指向
引用数据类型真正的内容在堆内存中
基本数据类型是数值传递
JSP 中 JSTL 和 EL 操作,帮助用户回避掉转型操作
package demo; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class Student{ private String name; public Student(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public class StringTest { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { // 向上转型 Object obj = new Student("Tom"); Class<?> clazz = obj.getClass(); Method method = clazz.getMethod("getName"); System.out.println(method.invoke(obj)); // Tom } }
泛型通配符
package demo; interface IMessage{ void print(); } class TextMessage implements IMessage{ @Override public void print() { System.out.println("TextMessage"); } } class Factory{ public static <T> T getInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException { return clazz.newInstance(); } } public class FactoryDemo { public static void main(String[] args) throws InstantiationException, IllegalAccessException { IMessage message = Factory.getInstance(TextMessage.class); message.print(); } }
泛型中的“T”与“?”的区别?
<T> 用于泛型类声明 <?> 用于方法接收参数,或者返回类型 只能取得内容,不能设置内容
虚拟内存
操作系统会将硬盘进行内存虚拟化
相当于硬盘可以模拟内存
Java8 开始取消了永久代,使用元空间来进行操作
面试题
代码块(常用语 junit)
- 普通代码块
- 构造代码块 优先于构造方法
- static 代码块 优先于构造方法,优先于主方法
- 同步代码块
子类实例化一定会默认执行父类构造方法,再执行子类自己的构造方法
程序执行是由父到子的顺序执行
package demo; class A { static { System.out.println("1"); } public A() { System.out.println("2"); } } class B extends A { static { System.out.println("3"); } public B() { System.out.println("4"); } } public class StringTest { public static void main(String[] args) { A a = new B(); a = new B(); } }
执行结果
A a = new B(); 1 -> static { System.out.println("1"); } 3 -> static { System.out.println("3"); } 2 -> public A() { System.out.println("2"); } 4 -> public B() { System.out.println("4"); } a = new B(); 2 -> public A() { System.out.println("2"); } 4 -> public B() { System.out.println("4"); }
转义字符处理
\\ \n \t
正则中写法
\\d
资源注入
@Resource、@Autowired 两个注解都是直接利用反射进行对象的引用设置
IO
异步 IO 等待返回后继续
同步 IO 不等待返回,直接继续
BIO Blocking 同步阻塞 IO 传统模式
NIO Non-blocking 同步非阻塞 IO 零拷贝
AIO Asynchronous 异步非阻塞 IO
字节流与字符流
所有磁盘保存的文件和网络传输的文件实际上都是字节数据
为了处理中文更方便,使用字符流来操作
内存流和管道流
内存流:需要产生 IO 的情况下,但是又不希望产生实际的存储文件所采用的一种 IO 方案
管道流:来自 Unix 系统中的概念,指的是两个进程之间的通讯关系,同一个程序由于运行的进程不同,所以其拥有各自的数据存储空间
Java 并没有进程的开发,是多线程编程语言
Python 提供多进行程开发,还有协程开发
Java 在多线程的结构上使用了管道的概念
缓存流与内存流
内存流: 将所有数据在内存之中进行完整的处理操作
缓存流:暂时的操作, Scanner