1.Java什么时候用重载,什么时候用重写?
重载是多样性,重写是增强剂。
Java中的重载overload最重要且最常用的应用场景是构造器的重载,构造器重载后,提供多种参数形式的构造器,可以应对不同的业务需求,加强程序的健壮性和可扩展性。比如Spring源码中的ClassPathXmlApplicationContext,他的构造函数使用重载一共提供了10个构造函数,这样就为我们的业务选择提供了多样性。在应用到方法中时,主要是为了增强方法的健壮性和可扩展性。再比如我们目前工作中的短信工具SMSUtil,发短信的方法就会重载,针对不同业务场景下的不同形参,提供短信发送方法,这样又提高了工具类的扩展性和健壮性。
总结:重载必须要修改方法的形参列表,可以修改方法的返回值类型,也可以修改方法的异常信息即访问权限;使用范围是同一个类中,目的是对方法的功能进行扩展,以应对多业务场景的不同使用需求。
Java中的重写主要用于子类对父类方法的扩展和修改,但是在我们实际开发中,为了避免程序混乱,重写一般都是为了方法的扩展,比如在cglib方式实现的动态代理中,代理类就是继承了目标类,对目标类的方法进行重写,同时在方法前后进行切面注入。
总结:方法重写时,参数列表和返回值类型时一定不能修改的,异常可以减少或者删除,但是不能抛出新的或者更广的异常,方法的访问权限可以降低限制,但是不能做更严格的限制。
2.举例一个更倾向于抽象类,而不是使用接口的设计场景。
接口是一种定义,抽象类是一种抽象的实现,比较典型的使用就是模板方法:在使用模板方法定义某种操作流程时,更倾向于使用抽象类,比如JDBCTemplate.举例:获取第三方数据,在一个项目中我们要获取芝麻分,法院的信用报告,运营商报告,我们会使用一个抽象类来定义整个流程。1、参数设置,2、数据获取,3、结果解析,4、结果存储,5、日志记录;在这个场景里面,比较适用于使用抽象类来定义整个业务流程,具体的数据获取和结果解析交给子类来处理。这是个典型的模板方法模式。使用抽象类可以定义关键步骤和指定执行流程。而如果使用接口,则并不合适。
3.在java中如何应用多线程?
1.继承Thread类(本质上是对Runnable接口的实现)
2.实现Runnable接口
3.Callable/Future带返回值的线程
4.ThreadPool
4.线程的生命周期?
Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程
5.线程的启动为什么要用start()方法?
在Thread类中,start()方法是一个同步启动的方法。在start()方法内部调用了一个start0的方法。而start0()方法是一个native方法。在JVM层面可以发现start0对应JVM_StartThread。线程的启动就是由JVM_StartThread完成的。在JVM_StartThread中基于os去进行一个线程的启动操作,线程启动之后会回调run()方法。
http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/00cd9dc3c2b5/src/share/native/java/lang/Thread.c (定位JVM_StartThread)
jvm.cpp(在HotSpot源码中可以找到JVM_StartThread)
6.线程的终止?
推荐使用interrupt()方法当其他线程通过调用当前线程的 interrupt 方法,表示向当前线程打个招呼,告诉他可以中断线程的执行了,至于什么时候中断,取决于当前线程自己。线程通过检查资深是否被中断来进行相应,可以通过isInterrupted()来判断是否被中断。
7.synchronized->锁在内存中的布局?
8.在Java中为什么不允许静态方法中访问非静态变量?
静态变量:被static关键字修饰的变量,称为静态变量或者类变量。
实例变量:即非静态变量,没有被static关键字修饰的变量。
JVM层面,程序运行时,只要程序加载了类的字节码,静态变量就会被分配内存空间。换言之,静态变量可以被称为类变量,静态变量不属于某个对象。
而实例变量则不同,实例变量是属于对象的属性,必须创建了对象,实例变量才会被加载分配内存空间
所以静态方法中无法访问非静态变量。
为什么这样设计?
1.方便在没有创建对象的情况下进行调用,比如设计公共工具类。
2.static修饰的静态代码块,在类加载的时候只会执行一次。可以用来优化程序性能。
9.列举你所了解的软件分层场景、软件分层有那些好处?
假如我们初次了解到Spring AOP的概念,我们在看到源码的时候便可以清楚地知道spring-aop这个模块就是Sping AOP思想地具体实现。这个时候我们回顾AOP地概念-面向切面编程-把那些影响多个类的行为封装到可重用的模块中去。、
这个时候具体怎么实现的我们需要通过源码去了解,在spring-aop模块中有一个包叫做intercept:拦截。这个时候我们就有了一个模糊的概念,Spring AOP 是通过拦截的方式去把影响多个类的行为去封装到可重用的模块中。这无疑给我们的学习提供了一个较为清晰的方向。
总结:软件分层不是为了分层而分层,而是为了让我们去思考如何让我们的代码具有更高的
扩展性,可读性等等