1.Object有多少个函数?
Object有九个函数:
- final Class <? extends Object> getClass()返回一个对象的运行时类,例如下面的代码:
`
public class ObjectTest<T> extends Object{
public static void main(String[] args) {
Object a = new ObjectTest<String>();
Object b = new ObjectTest<Integer>();
System.out.println(a.getClass());
System.out.println(b.getClass());
System.out.println((new ObjectTest<String>()).getClass());
System.out.println(a.hashCode());
System.out.println(b.hashCode());
}
}
返回结果相同,getClass都是返回ObjectTest,都是相同的。 - int hashCode:Java程序运行期间,在同一个对象对此调用此函数,必须返回相同值,前提是equals比较所用信息没有被修改。如果equals方法判定两个对象相等,那么hashCode生成相同的整数结果。如果equals判定不相等,hashCode一定产生不同整数结果。Object类定义的hashCode方法确实会针对不同的对象返回不同值,一般是通过将该对象的内部地址转换为一个整数来实现。
- boolean equals,自反对称传递。
- Object clone() throws CloneNotSupportedException,必须要将Clonable接口实现才能调用,否则抛出异常。Clonable接口本身并无内容,只是表明此对象可以使用Clone函数。
- toString
- finalize()方法,JVM内存回收时调用,如果子类覆盖了,对象一定要执行一次内存回收。
- wait 导致当前线程等待,直到该对象的notify或notifyAll被执行。即申请持有锁。
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
该方法必须同步执行的,否则会抛出IllegalMonitorStateException。 - notify 随机选择一个对象,解除阻塞状态,告知锁解除。智能在同步方法或同步方法块中执行,且调用者必须持有锁。
- notifyall 通知所有线程。其余与上者相同。
2.JVM的垃圾回收机制介绍?
见第四条OOM发生。
3.介绍GNU?操作系统加载?
4.Object的HashCode如果不实现的话返回值是什么?
由地址转换的hash值。
1.做了什么项目?了解什么框架?
2.数据库范式定义?
参考:http://www.cnblogs.com/zhanht/p/5401699.html
参考:http://blog.csdn.net/qingking520/article/details/52937728
第一范式(1NF):属性(实体所具有的某一特性)不可分。
第二范式(2NF):满足第一范式,并且,一定要有一个主键,非主属性完全依赖于主键。一个属性在候选码中出现就是主属性。与之相对的就是非主属性。完全指不是部分,而是全部。
第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。依赖传递。即依赖是唯一的。
BC范式(BCNF):符合3NF,并且,主属性不依赖主属性。
第四范式:要求把同一表内多对多关系删除。
第五范式:从最终结构建立原始结构。
3.排序算法?
4.Java内存溢出?
简述下个人思路:JVM运行时数据区域包括线程私有的本地方法栈、虚拟机栈、程序计数器,线程共享的方法区和堆。会发生OOM的公有本地方法栈(栈可以动态扩展,否则StackOverFlowError)、虚拟机栈(栈可以动态扩展)、方法区(包括方法区和运行时常量池)、堆(大头)。
什么时候发生OOM(主要以堆来阐述),当堆(新生代,主要是Eden)没有足够的内存时发起一次MinorGC(针对新生代,复制法,其余还有标记-清楚、标记-整理),使用可达性分析(Python计数法);如果晋升导致老年代满了,则触发一次MajorGC(老年代)。永久代满了使用FullGC(清理整个空间,包括永久代)。执行完了发现还没有内存,才OOM。
5.线程与进程的区别?
线程调度的单位,进程是资源分配的单位。
6.为什么要序列化?什么场景用到?有哪些方法?弊端?
序列化:将一个对象编码成一个字节流,称作将该对象序列化;相反的过程称为反序列化。
应用场景:对象被序列化后,其编码就能从一台虚拟机传输到另外一台虚拟机,或者存储到磁盘上。
如何实现:
- 实现Serializable接口
将Java对象根据属性值转换为字节序列,transient。static关键字则没办法实例化,举例(HashMap的modCount)。场景,持久化、网络传输、进程通信、缓存等。Serializable实际上就是用了一个独立于你实现构造函数之外的构造函数去创建
弊端:1.大端小端2.破坏单例。
付出的代价(隐含了可能的失败): - 如果没有显示化声明私有静态的final的long域下的UID,则系统会更具类的实现自动生成该标识,那么,当修改类的时候,可能造成发布版本的变化。
- 增加了出现Bug和安全漏洞的可能性。通常情况下对象是利用构造器来创建的,序列化机制是一种语言之外的对象创建机制。因此反序列化具备与其他构造器相同的特点,由于没有显示的构造器,很可能导致疏忽构造过程的规约。
- 加大测试负担。
- 尽量不使用自定义序列化形式,使用默认序列化形式将出很多状况,具体详见《Effective Java》第75条。
- 序列化植入代码,引用指向本对象可变的引用,导致程序发生不可逆转的变化,《Effective Java》第76条。
- 反序列化破坏单例模式,详情见《Effective Java》第77条。
7.java反射机制的实现原理
所谓反射机制就是java语言运行时拥有一项自观的能力。通过这种能力可以彻底了解自身的情况为下一步的动作做准备,Java反射机制的实现主要借四个类:class、Constructor、Field、Method。
反射是指在运行时能查看一个类的状态及特征,并能进行动态管理的功能。
反射的应用场景:在Java程序中许多对象在运行时都会出现两种类型:编译时类型和运行时类型。编译时的类型由声明该对象时使用的类型决定,运行时的类型由实际赋给对象的类型决定
如:Person p =new Student();
编译时类型为Person,而运行时为Student。
除此之外,程序在运行时还可能接收到外部传入的一个对象,该对象的编译时类型为Object,但程序又需要调用该对象运行时类型的方法。为了这些问题程序需要在运行时发现对象和类的真实信息。然而,如果编译时根本无法预知该对象和类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息,此时就必须使用反射。
7.1 java的类装载系统与反射
其实也是一个java类加载和对象初始化过程。
java虚拟机中有两种类装载器:启动类装载器和自定义类装载器。前者是jvm的一部分,后者是java程序的一部分,不同的装载器放在不同的命名空间中。
反射是以免镜子,能够在镜子中看到这个类中“所有”的东西。
有三种方法可以在程序中获得class:
- 使用Class中的forname()静态方法获得class对象。
- 得到该类的一个对象使用(Object九大方法之一)getClass获得。
- 运行时已经知道类名,使用类名.class获得。
而反射在JVM中的实现如下: - 一、Class.forName的实现:在JDK中,可以发现最终调用的是native方法forName0(),它在C中调用的实际是findClassFromClassLoader(),原理与ClassLoader的流程(加载、连接)一样。
- 二、getDeclaredFields0的实现:在JDK源码中,可以知道class.getDeclaredFields()方法实际调用的是native方法getDeclaredFields0(),它主要实现步骤如下:
1.根据Class结构体信息,获取field_count与fields[]字段,这个字段早已在load过程中被放入了
2.根据field_count的大小分配内存、创建数组。
3.将数组进行forEach循环,通过fields[]中的信息依次创建对象。
4.返回数组指针。 - 三、Method.invoke的实现:
1.创建Frame
2.如果对象flag为native,交给native_handler进行处理
3.在frame中执行java代码
4.弹出Frame
5.返回执行结果的指针 - 四、class.newInstance的实现:
1.检测权限、预分配空间大小等参数
2.创建Object对象,并malloc分配空间
3.通过Method.invoke调用构造函数(<init>())
4.返回Object指针
(tips:java类加载将将.class中的二进制流文件转化为方法区(内存)中的Class对象)
7.2 JavaRTTI与反射
RTTI(Run-Time Type Identification,通过运行时类型识别)的含义就是在运行时识别一个对象的类型,其对应的类是Class对象,每个java里面的类都对应一个Class对象(在编写并且编译后),这个对象被保存在这个类的同名class文件里。
类加载器在类被第一次静态调用(见java类加载)时会把那个对应的Class对象加载到内存中。
根据上文可以知道,获取Class独享有三种方法。通过Class对象用户可以在运行时动态得到大量关于这个类的信息,包括接口,父类,方法,静态成员,甚至是像newInstance()方法这样的一个实现“虚拟构造器”的一种方式。所谓的虚拟构造器,就是声明“我不知道你的确切类型,至少在编译期不知道,但是我就是要正确的创建你的一个对象”。
RTTI的核心:Class对象、instanceof关键字、强制类型装换。
RTTI的限制?显然它在编译时必须知道一个非常重要的东西:类名(全类名)
Java中有时候在编译器为程序生成代码很久之后才会出现要处理的那个类,那么这个时候怎么才能处理这个类呢,即在编译的时候根本无法获知这个对象所属的类。答案就是利用Java的反射机制。Java的反射与RTTI的区别就在于编译时不需要知道任何事情,匿名对象的信息在运行时确定下来就可以。
8.Java是如何处理整型的溢出和下溢的?
Java更具类型的大小,将计算结果中的对应低阶字节存储到对应的值里。