Java面试的一些总结

来源:互联网 发布:心中的秘密知乎 编辑:程序博客网 时间:2024/05/21 10:19

1.为什么Java中的静态方法不能是抽象的?
概念问题:
static静态方法又叫类方法,意义在于不用实例化对象即可直接调用,
而abstract 修饰的抽象方法,是没有方法体的,本身没有任何意义,它
的价值在于被继承重写,但是重写是基于对象的。所以这两者从最基本的概念都是冲突的。

2.静态方法可以被重写吗?

public class StaticTest  {      public static void main(String[] args)      {          M m = new N();          m.output();      }  }  class M  {      public static void output()      {          System.out.println("M");      }  }  class N extends M  {      public static void output()      {          System.out.println("N");      }  }  

上面执行的结果是“M”,也就是是M类型的引用调用的,如果修改main方法中的代码:
N n = new N();
n.output();
那么执行的结果是“N”,也就是N类型的引用调用的。

父类的普通方法可以被继承和重写,不多作解释,如果子类继承父类,而且子类没有重写父类的方法,但是子类会有从父类继承过来的方法。

静态的方法可以被继承,但是不能重写。如果父类中有一个静态的方法,子类也有一个与其方法名,参数类型,参数个数都一样的方法,并且也有static关键字修饰,那么该子类的方法会把原来继承过来的父类的方法隐藏,而不是重写。通俗的讲就是父类的方法和子类的方法是两个没有关系的方法,具体调用哪一个方法是看是哪个对象的引用;这种父子类方法也不在存在多态的性质。《Java编程思想》中这样提到“只有普通的方法调用可以是多态的”。

静态的方法不能覆写,也不能被重写。总之,静态的没有重写!!!

3.为什么静态成员、静态方法中不能用this和super关键字?

在静态方法中是不能使用this预定义对象引用的,即使其后边所操作的也是静态成员也不行,因为this代表的是调用这个函数的对象的引用,而静态方法是属于类的,不属于对象,静态方法成功加载后,对象还不一定存在。

super的用法跟this类似,this代表对本类对象的引用,指向本类已经创建的对象;而super代表对父类对象的引用,指向父类对象;

this和super是属于对象范畴的东西,而静态方法是属于类范畴的东西。
静态方法和静态成员不属于单个对象,而是类的所有对象共享使用,而this代表当前对象,super代表对父类对象,东西只属于类,不属于任何对象,所以不能用this和super。

4.抽象类和接口的对比:

这里写图片描述

抽象类可以没有抽象方法,但是如果你的一个类已经声明成了抽象类,即使这个类中没有抽象方法,它也不能再实例化,即不能直接构造一个该类的对象。如果一个类中有了一个抽象方法,那么这个类必须声明为抽象类,否则编译通不过。

5、Servlet的生命周期
Servlet的生命周期一般分四步,
加载–>初始化–>服务–>销毁

1)加载:
加载一般是在运行tomcat容器时来完成,将servlet类加载到tomcat中,或者是客户端发来请求时也可以

2)初始化:
初始化一般是调用init()方法读取配置信息、读取初始化参数等,这些基本上在整个生命周期中只需要执行一次。

3)服务:
服务一般是当容器接收到客户端请求时,Servlet引擎将创建一个ServletRequest请求对象和一个ServletResponse响应对象,然后把这两个对象作为参数传递给对应Servlet对象的service方法。(该方法是一个重点实现的方法,ServletRequest对象可以获得客户端发出请求的相关信息,如请求参数等,ServletResponse对象可以使得Servlet建立响应头和状态代码,并可以写入响应内容返回给客户端。在此说明一点,当Servlet中有doGet()或者doPost()方法时,那么service方法就可以省略,默认为调用这两个方法)

4)销毁:
销毁一般是Servlet的卸载是由容器本身定义和实现,在卸载Servlet之前需要调用destroy()方法,以让Servlet自行释放占用的系统资源。虽然Java虚拟机提供了垃圾自动回收处理机制,但是有一部分资源却是该机制不能处理或延迟很久才能处理的,如关闭文件,释放数据库连接等。

6、类加载机制
概念:
Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。

(1) 装载:类的装载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

(2)校验:验证的目的是为了确保Class文件中的字节流包含的信息符合当前虚拟机的要求,而且不会危害虚拟机自身的安全。不同的虚拟机对类验证的实现可能会有所不同,但大致都会完成以下四个阶段的验证:文件格式的验证、元数据的验证、字节码验证和符号引用验证。
a)文件格式的验证:验证字节流是否符合Class文件格式的规范,并且能被当前版本的虚拟机处理,该验证的主要目的是保证输入的字节流能正确地解析并存储于方法区之内。经过该阶段的验证后,字节流才会进入内存的方法区中进行存储,后面的三个验证都是基于方法区的存储结构进行的。
b)元数据验证:对类的元数据信息进行语义校验(其实就是对类中的各数据类型进行语法校验),保证不存在不符合Java语法规范的元数据信息。
c)字节码验证:该阶段验证的主要工作是进行数据流和控制流分析,对类的方法体进行校验分析,以保证被校验的类的方法在运行时不会做出危害虚拟机安全的行为。
d)符号引用验证:这是最后一个阶段的验证,它发生在虚拟机将符号引用转化为直接引用的时候(解析阶段中发生该转化,后面会有讲解),主要是对类自身以外的信息(常量池中的各种符号引用)进行匹配性的校验。

(3)准备:给类的静态变量分配存储空间以及对静态变量初始化;这些内存都将在方法区中进行分配。

注意:
a)这时候进行内存分配的仅包括类变量(static),而不包括实例变量,实例变量会在对象实例化时随着对象一块分配在Java堆中。
b)这里所设置的初始值通常情况下是数据类型默认的零值(如0、0L、null、false等),而不是被在Java代码中被显式地赋予的值。

(4)解析:将符号引用转成直接引用;
符号引用和直接引用:
在java中,一个java类将会编译成一个class文件。在编译时,java类并不知道引用类的实际内存地址,因此只能使用符号引用来代替。比如org.simple.People类引用org.simple.Tool类,在编译时People类并不知道Tool类的实际内存地址,因此只能使用符号org.simple.Tool(假设)来表示Tool类的地址。而在类装载器装载People类时,此时可以通过虚拟机获取Tool类 的实际内存地址,因此便可以既将符号org.simple.Tool替换为Tool类的实际内存地址,及直接引用地址。

(5)初始化:到了初始化阶段,才真正开始执行类中定义的Java程序代码。
为类的静态变量赋予正确的初始值,JVM负责对类进行初始化,主要对类变量进行初始化。

参考:http://blog.csdn.net/fgets/article/details/52934178

7、Java虚拟机的内存模型

这里写图片描述

原创粉丝点击