对象的实例化
对象的实例化、内存布局、访问定位对象的实例化创建对象的方式
new
最常见的方式
变形1:xxx的静态方法
变形2:xxxBuilder/xxxFactory的静态方法
Class的newInstance():反射的方式,只能调用空参的构造器,权限必须是public
Constructor的newInstance(xxx):反射的方法,可以调用空参、带参的构造器,权限没有要求
使用clone():不调用任何构造器,当前类需要实现Cloneable接口,实现clone()
使用反序列化:从文件、从网络中获取一个对象的二进制流
第三方库
创建对象的步骤
判断对象对应的类是否加载、链接、初始化
虚拟机遇到一条new指令,首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载、解析和初始化。(即判断类元信息是否存在)。如果没有,那么在双亲委派模式下,使用当前类加载器以ClassLoader+包名+类名为Key进行查找对应的.class文件,如果没有找到文件,则抛出ClassNotFound异常,如果没有找到 ...
SPI机制
简述全程Service Provide Interface,是Java中提供的一种服务发现机制
它允许应用程序动态地加载和使用第三方提供的服务实现
而无需在代码中显示引用这些实现类
Java SPI是基于接口编程思想的具体体现,通过服务接口和其实现分离,从而具备更好的可扩展性和可维护性
如何定义一个SPI
定义一个接口
1234package com.wereash.spi;public interface SayService(){ void say();}
提供一个或多个实现了该接口的实现类,作为服务提供者
12345678package com.wereash.spi;public class SayChinese implements SayService{ @Override public void say(){ System.out.println("你好"); }}
配置文件。在src/main/resource下新建M ...
SpringBoot starter
starter组件是SpringBoot四大核心功能特征之一
除此之外,还有
自动装配
Actuator监控
目的是为了让开发者在开发Spring生态应用时,只需要关注业务逻辑,减少对配置和外部环境的依赖
Starter组件核心功能:
以功能为维度,来维护对应jar包的版本依赖,那么开发者就不需要去关心例如:版本冲突这些容易出错的细节
Starter组件会把对应功能的所有的jar包依赖全部导进来
Starter内部集成了自动装配机制,程序依赖对应的Starter组件之后,会自动集成到Spring生态里面,并且对于相关bean的管理也是基于自动装配实现的
组件对应功能所需要维护的外部化配置,会自动集成在Spring Boot里面,我们只需要在application.properties进行维护配置
官方维护的starter组件:spring-boot-starter-xxx
第三方维护的starter:xxx-spring-boot-starter
wait与notify
wait与notify为什么要放在synchronized中wait和notify是用来实现多个线程之间的一个协调
wait表示让线程进入阻塞状态
notify表示让阻塞线程唤醒
wait和notify是成对出现的,如果一个线程被wait方法阻塞了,那么必然需要另外一个线程通过notify方法进行唤醒,从而实现多个线程之间的通信
在多线程中,要实现多个线程之间的通信,除了管道流之外,只能通过共享变量的方法来实现,也就是说线程t1修改线程变量s,线程t2获得修改后的共享变量s的值,从而去完成线程之间的通信,但是多线程具有并行执行的特性,就是说在同一个时刻,多线程可以通知来操作共享变量。
那么线程t2就必须直到t1已经修改了共享变量s,否则就要进行等待,t1在修改之后,必须要将处在等待的线程t2唤醒
这个时候就需要一个静态条件,去控制线程什么时候条件等待,而什么时候条件唤醒
而synchronized同步关键字就可以实现这样一个互斥的条件
也就是在通过共享变量来实现多线程通信的场景下,参与通信的线程必须要去竞争到这个共享变量的一个锁资源,才能够对共享变量进行修改,修改完之后释放锁,其他 ...
Java常用函数
Java常用函数Math类中
ceil() 方法
cell()方法可以对一个数进行向上取整
double ceil(double d)
double ceil(float f)
pow
a^b次方
Math.pow(double a,double b)
Scanner类中
Spring Bean
Spring Beanbean的作用域
在Spring中可以通过配置bean标签的scope属性来指定bean的作用域范围,各取值含义参考如下表:
取值
含义
创建对象的时机
singleton(默认)
在IoC容器中,这个bean的对象始终为单实例
IoC容器初始化时
prototype
这个bean在IoC容器中有多个实例
获取bean时
多实例——每个实例地址不同
bean的生命周期Spring Bean的生命周期是从 Bean 实例化之后,即通过反射创建出对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为Spring Bean的生命周期。Spring Bean的生命周期大体上分为三个阶段:
Bean的实例化阶段: Spring框架会取出BeanDefinition的信息进行判断当前Bean的范围是否是singleton的是否不是延迟加载的,是否不是FactoryBean等,最终将一个普通的singleton的Bean通过反射进行实例化;
Bean的初始化阶段: Bean创建之后还仅仅是个”半成品”,还需要对Bean实例的属性进行填充 ...
类加载过程
类加载过程Java文件通过javac编译成class文件,这种中间码被称为字节码,然后由JVM加载字节码。
运行时,解析器将字节码解释为一行行的机器码执行,在程序运行期间,即时编译器会针对热点代码将该部分字节码编译成机器码以获得更高的执行效率。
在整个运行时解释器和即时编译器的相互配合使Java程序几乎能够达到和编译型语言一样的执行速度
把一份被javac编译过的class文件文本,通过加载生成某种形式的Class数据结构进入内存,程序可以调用这个数据结构来构造出object,这个过程是在运行时进行的,是Java动态扩展性的根基
在类加载过程中,只有加载步骤中的读取二进制流与初始化部分,能够被上层开发者,也就是大部分的Java程序员控制,而剩下的所有步骤,都是由JVM控制,其中细节由JVM的开发人员处理,对于上层开发者来说是个黑盒
加载Loading加载就是一个读取Class文件,将其转化为某种静态数据结构存储在方法区内,并在堆中生成一个便于用户调用的java.lang.Class类型的对象的过程
通过一个类的全限定名获取定义此类的二进制字节流
将这个字节流所代表的静态存储结构转化 ...
SpringMVC工作流程
SpringMVC的执行流程以及运行原理什么是MVCMVC 是 Model、View 和 Controller 的缩写,分别代表 Web 应用程序中的 3 种职责,MVC是一种软件设计规范。它将业务逻辑、数据、显示分离的方法来组织代码,降低了视图与业务逻辑之间的双向耦合
Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。
Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。
最典型的MVC模式就是JSP+Servlet+JavaBean的模式。
什么是SpringMVC
SpringMVC是一个基于MVC模式的Web框架,是Spring框架的 ...
类加载器
类加载器的分类
JVM支持两种类型的类加载器,分别是引导类加载器(BootStrap ClassLoader)和自定义类加载器(User-defined ClassLoader)
从概念上讲,自定义类加载器一般指的是程序中由开发人员自定义的一类加载器,但是Java虚拟机规范却又没这么定义,而是将所有派生于抽象类的ClassLoader的类加载器划分为自定义类加载器
启动类加载器(引导类加载器)Bootstrap ClassLoader
这个类加载器使用C/C++语言实现的,嵌套在JVM内部
它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar、resources.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类
并不继承自java.lang.ClassLoader,没有父加载器
加载扩展类和应用程序类加载器,并指定为他们的父类加载器
出于安全考虑,Bootstrap启动类加载器只加载包java、javax、sun等开头的类
扩展类加载器(Extension ClassLoade ...
Java新特性表达式
Java8新特性Lambda表达式
lambda表达式形式:参数, 箭头(->) 以及一个表达式。如果代码要完成的计算无法放在一个表达式中,就可以像写方法一样,把这些代码放在 { }中,并包含显式的 return语句
即使 lambda 表达式没有参数, 仍然要提供空括号,就像无参数方法一样: () -> { for (int i = 100;i >= 0;i ) System.out.println(i); }
无需指定 lambda 表达式的返回类型。lambda 表达式的返回类型总是会由上下文推导得出。例如,下面的表达式(String first, String second) -> first.length()- second.length()
也可以忽略其类型,由编译器推出其类型( first, second) -> first.length()- second.length()
12345678910111213141516171819202122232425262728293031323334353637publ ...