javaSE知识概括
java类中各成员初始化的顺序
代码示例:
class Father
{
static{
System. out.println("父类静态代码块初始化" );
}
{
System. out.println("父类代码块初始化" );
}
private static String s=print();
public static String print()
{
System. out.println("父类静态方法" );
return "父类静态成员变量的初始化" ;
}
public Father()
{
System. out.println("父类无参构造函数初始化完成" );
show();
}
public void show()
{
System. out.println("父类show()方法" );
}
}
class Son extends Father
{
static{
System. out.println("子类静态代码块初始化" );
}
{
System. out.println("子类代码块初始化" );
}
private static int i=1;
private String s="子类私有成员变量" ;
public void show()
{
System. out.println("子类show()方法:i=" +i);
}
public Son()
{
System. out.println("子类构造函数初始化完成" );
show();
}
}
public class TestClassLoadSeq {
public static void main(String[] args)
{
new Son();
}
}
- 输出结果:
父类静态代码块初始化
父类静态方法
子类静态代码块初始化
父类代码块初始化
父类无参构造函数初始化完成
子类show()方法:i=1
子类代码块初始化
子类构造函数初始化完成
子类成员变量初始化完成:s=子类私有成员变量
子类show()方法:i=1
从结果可以看出类中各成员初始化的顺序是:
- 如果类中存在继承关系(像 Son 继承 Father) 则首先会初始化导出类(Son)的基类(Father),然后再是导出类
- 在基类首先会初始化静态 的东西 静态块>静态变量 而且只初始化一次 (因为静态的东西都是跟着类的加载而加载的)
- 随后就是初始化导出类的静态东西 跟基类的静态初始化一样(同上)
- 初始化基类无参构造器(调用有参就初始化有参构造器)
- 初始化导出类无参构造器(注意:导出类的成员变量和代码块都是是比构造函数的初始化要早。。看输出结果可知)
在上面输出结果可能会看到在基类中的构造器中调用了show() 方法:
- 这样的输出可能不奇怪,代码示例:
class Father
{
private static String s= print();
static{
System. out.println("父类静态代码块初始化" );
}
{
System. out.println("父类代码块初始化" );
}
public static String print()
{
System. out.println("父类静态方法" );
return "父类静态成员变量的初始化" ;
}
public Father()
{
System. out.println("父类无参构造函数初始化完成" );
show();
}
public void show()
{
System. out.println("父类show()方法" );
}
}
class Son extends Father
{
static{
System. out.println("子类静态代码块初始化" );
}
{
System. out.println("子类代码块初始化" );
}
private int i =1;
private String s="子类私有成员变量" ;
public void show()
{
System. out.println("子类show()方法:i=" +i);
}
public Son()
{
System. out.println("子类构造函数初始化完成" );
System. out.println("子类成员变量初始化完成:s=" +s);
show();
}
}
public class TestClassLoadSeq {
public static void main(String[] args)
{
new Son();
}
}
- 输出结果:
子类静态代码块初始化
父类代码块初始化
父类无参构造函数初始化完成
子类show()方法:i=0
子类代码块初始化
子类构造函数初始化完成
子类成员变量初始化完成:s=子类私有成员变量
子类show()方法:i=1
- 可以看出跟上面的代码没有什么不同,唯一的不同就是我把导出类中的静态成员变量i 变成了成员变量i,可以看出结果是截然不同,现在的结果是:0
- 原因:因为上面的静态成员变量是跟着类的加载而初始化的 所以结果是1 而下面的是成员变量又因为现在还在基类构造器中所以导出类中的成员变量还没有得到初始化 所以是0
- 所以上面的初始化顺序不够完整,现在补全下:
①首先jvm加载类时 会对每个对象的默认初始化 为0,对通过组合方式的引用类型默认初始化为null
总结:
- java中首先初始化基类在初始化导出类(有多少个基类初始化多少个)
创建对象的步骤:
hook钩子
简介:
- Hook是Windows中提供的一种用以替换DOS下“中断”的系统机制,中文译为“挂钩”或“钩子”。在
- 对特定的系统事件进行hook后,一旦发生已hook事件,对该事件进行hook的程序就会收到系统的通知,这时程序就能在第一时间对该事件做出响应。
Java中的hook:
- 请问在Spring中,如果JVM异常终止,Spring是如何保证会释放掉占用的资源,比如说数据库连接等资源呢?
答:定义钩子方法。
- 我们知道在Spring中定义销毁方法有两种方式:
①实现 DisposableBean 的 destroy 方法。
②使用@PreDestroy 注解修饰方法
@Component
public c1ass DatacollectBean implements DisposableBean {
//第一种方法实现DisposableBean destroy方法·
public void deatroy() throws Exception {
System.err.print1n(“执行销毁方法”):
}
//第二种方法使用PreDestroy注解声明销毁方法
@PreDestroy
public void customerDestrOy(){
system.err.printin( "执行自定义销毁方法");
}
那么在什么时候执行销毁方法?
主动执行销毁bean
pablic static void main(String1 args){
ConfigurableApplicationContext run =
SpringApplication.run(DemoApplication.class,args);
DatacollectBean bean = run.getBean (DatacollectBean.class);
//主动销毁bean
run.getBeanraetory().dastroyBean(bean);
- JVM关闭时候自动执行销毁方法。 这里就要用到钩子函数了, Spring 的钩子函数在
AbstractApplicationContext#shutdownHook属性。如果我们是SpringBoot项目我们看到在SpringApplication启动时候会注册一个钩子函数
private void refreshContext(ConfigurableApplicationContext context){
refresh(context):
if(this.registerShutdowniHook){
try {
context.registerShutdownHook():
}
catch (AccesscontrolException ex){
}
}
}
如何定义钩子函数?
publie classHooksTester {
publie static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable(){
@override
public void run(){
System.out-println[一钩子函数执行”;
}
}));
//当主动关闭应用
while (true);
}
总结:
- 触发钩子函数的场景:
- 钩子函数能做什么?
①正如上图所示优雅停机,在项目将要关闭时候,主动释放程序占用的资源信息,释放db连接池的连接等其他占用的资源信息。 如果我们是 Spring 项目其实我们不用自己定义钩子函数,我们只要使用Spring提供给我们的销毁方法即可。因为 Spring定义的钩子函数中会去执行, DisposableBean.destory() 和被 PreDestroy 修饰的方法。 - 链接:Hook钩子函数
内部类和对象与类的匿名
内部类和对象与类的匿名简介:
- 对象与类的匿名:
①匿名对象就是该类实例化后直接使用,不赋予标识符。
②匿名类就是直接实例化一个类且该类只能被实例化一次,形式与实例化一个对象差不多。
③区别:一个在于类的一次性,一个在于对象的一次性。
- 内