TOC
Ⅰ. 反射
-
对反射的理解
- Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性
- 这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制
-
反射的示例
public class Robot { private String name; static { System.out.println("this is in static block"); } public void sayHi(String s) { System.out.println(s + " - " + name); } private String throwHello(String tag) { return "hello " + tag; } }
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException { Class robotClass = Class.forName("com.wnzhong.bjavaseadvance.areflect.Robot"); System.out.println("robotClass.getName() - " + robotClass.getName()); Method throwHello = robotClass.getDeclaredMethod("throwHello", String.class); throwHello.setAccessible(true); Robot robot = (Robot) robotClass.newInstance(); Object obj = throwHello.invoke(robot, "bob"); System.out.println(obj); Method sayHi = robotClass.getMethod("sayHi", String.class); sayHi.invoke(robot, "welcome"); Field name = robotClass.getDeclaredField("name"); name.setAccessible(true); name.set(robot, "alice"); sayHi.invoke(robot, "welcome"); }
-
反射的应用
-
JDBC 的数据库连接
- 通过 Class.forName() 加载数据库的驱动程序
- 通过 DriverManager 类进行数据库的连接,连接时要输入数据库的连接地址、用户名、密码
- 通过 Connection 接口接收连接
-
Spring 框架的通过 xml 配置模式装载 bean
- 将程序内所有 xml 或 properties 配置文件载入内存
- 解析配置文件内容,得到对应实体类的字节码字符串及相关属性信息
- 使用反射机制,根据字符串获取某个类的 Class 实例
- 动态配置实例的属性
-
Ⅱ. 动态代理
-
写一个 ArrayList 的动态代理类
-
动态代理 和 静态代理的区别及使用场景
-
静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类
-
静态代理事先知道要代理的是什么,而动态代理不知道要代理什么,只有运行时才知道
-
动态代理是实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象
-
还有一种动态代理 CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的
-
AOP 编程就是基于动态代理实现的,比如著名的 Spring 框架、 Hibernate 框架等等都是动态代理的使用例子。
-
Ⅲ. 设计模式
-
你知道哪些设计模式(23种)
-
创建型
- 工厂方法
- 抽象工厂
- 单例
- 建造者
- 原型
-
结构型
- 适配器
- 装饰器
- 代理
- 外观
- 桥接
- 组合
- 享元
-
行为型
- 策略
- 模版方法
- 观察者
- 迭代
- 责任链
- 命令
- 备忘录
- 状态
- 访问者
- 中介
- 解释器
-
-
单例模式
-
工厂模式
-
建造者模式
-
适配器模式
-
装饰模式
-
策略模式
-
观察者模式
Ⅳ. 回收机制
-
JVM 垃圾回收机制和常见算法
-
JVM 的内存结构和内存分配
-
Java 中的引用类型有哪些
-
heap 和 stack 的区别
-
解释内存中的 栈、堆、方法区 的用法
Ⅴ. 类加载器
-
Java 的类加载器的种类有哪些
-
类什么时候被初始化
-
ClassLoader 的双亲委托机制
-
描述一下 JVM 加载 class
-
获得一个类对象有哪些方式
Ⅵ. JVM
- 既然有了 GC 机制,为什么还会有内存泄漏情况
Ⅶ. GC
-
Java 为什么会有 GC 机制
-
哪些内存需要回收
-
什么时候回收垃圾
Ⅷ. Java8 新特性
-
lambda 表达式
- 实现 Runnable
- 进行事件处理
- 对列表进行迭代
- 函数式接口 Predicate
- map
- reduce
- filter
- 对列表每个元素应用函数
- distinct
- 最大值、最小值、总和、平均值
-
lambda 表达式要点
-
lambda 表达式的使用位置
- 预定义使用了 @FunctionalInterface 注释的函数式接口,自带一个抽象函数的方法。这些称为 lambda 表达式的目标类型,可以用作返回类型,或 lambda 目标代码的参数。
- 例如,若一个方法接收 Runnable、 Comparable 或者 Callable 接口,都有单个抽象方法,可以传入 lambda 表达式。
- 类似的,如果一个方法接受声明于 java.util.function 包内的接口,例如 Predicate、 Function、 Consumer 或 Supplier,那么可以向其传 lambda 表达式。
-
lambda 和方法引用
- lambda 表达式内可以使用方法引用,仅当该方法不修改 lambda 表达式提供的参数。
list.forEach(n -> System.out.println(n)); list.forEach(System.out::println);
-
lambda 内部引用资源
- lambda 内部可以使用静态、非静态和局部变量,这称为 lambda 内的变量捕获。
-
lambda 表达式也称闭包
- Lambda 表达式在 Java 中又称为闭包或匿名函数
-
lambda 表达式的编译方式
- Lambda 方法在编译器内部被翻译成私有方法,并派发 invokedynamic 字节码指令来进行调用。
- 可使用 JDK中的 javap 工具来反编译 class 文件。使用 javap -p 或 javap -c -v 命令来看一看 lambda 表达式生成的字节码
-
lambda 表达式的限制
- 只能引用 final 或 final 局部变量,这就是说不能在 lambda 内部修改定义在域外的变量
- 只是访问它而不作修改是可以的
-
-
Optional 类
-
描述:
- 这是一个可以为 null 的容器对象。如果值存在则 isPresent()方法会返回 true,调用 get()方法会返回该对象
-
方法:
- Optional.of()
- Optional.ofNullable()
- Optional.isPresent()
- Optional.get()
- Optional.ifPresent()
- Optional.orElse()
- Optional.orElseGet()
- Optional.orElseThrow()
- Optional.map()
- Optional.flatMap()
- Optional.filter()
-
Ⅸ. 内存溢出
-
常见原因
- 内存中加载的数据量过于庞大,如一次从数据库取出过多数据
- 集合类中有对对象的引用,使用完后未清空,使得 JVM 不能回收
- 代码中存在死循环,或循环产生过多重复的对象实体
- 启动参数内存值设定过小
-
如何解决
- 修改 JVM 启动参数,直接增加内存(-Xms,-Xmx 参数要添加)
- 检查错误日志,查看 OutOfMemory 错误前是否有其他异常或错误
- 对代码进行走查和分析,找出可能发生内存溢出的位置。重点排查如下:
- 检查数据库查询中是否有一次获取全部数据的查询:十万条记录就可能引起内存溢出;尽量采用分页查询方式
- 检查代码中是否有死循环或递归调用
- 检查是否有大循环重复产生新对象实体
- 检查 List、Map 等集合对象是否有使用完后未清除的问题。List、Map 等集合对象会始终存有对对象的引用,使得这些对象不能被 GC 回收
- 使用内存查看工具动态查看内存使用情况
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付
