【面试 JDK】【第一篇】Object类面试详解
1.Object类有哪些方法
1》clone()方法
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
2》getClass()方法
final方法,获得运行时类型。
3》toString()方法
常用方法,一般子类都会覆盖
4》finalize()方法
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
5》equals()方法
该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。
6》hashCode()方法
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
7》wait()方法
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
(1)其他线程调用了该对象的notify方法。
(2)其他线程调用了该对象的notifyAll方法。
(3)其他线程调用了interrupt中断该线程。
(4)时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
8》notify()方法
该方法唤醒在该对象上等待的某个线程
9》notifyAll()方法
该方法唤醒在该对象上等待的所有线程
===============================================================
2.==和equals()方法的区别
1》Object中的equals()方法就是做==
2》String中重写了equals()方法,在==比较之后还做了值的比较。
==比较地址是否相等
equals先比较地址是否相等,若不相等,再比较值是否相等。
3》上面说的==和equals()是在引用数据类型来说,在基本数据类型上 只有==比较,值是否相等。基本数据类型没有用equals()方法的比较。
===============================================================
3.clone()方法引申出来的克隆,关于深克隆和浅克隆的区别
1》浅克隆概念:仅克隆原对象的值给新的对象,原对象中如果有属性为对象,则仅克隆此属性的引用地址给新对象。即原对象和新对象对于一个属性对象是同一个引用地址。
2》深克隆概念:不仅克隆原对象的值给新对象,也会将原对象中对象属性重新开辟空间给新对象。
相关代码:
package com.sxd.test2; import lombok.AllArgsConstructor;
import lombok.Data; @Data
@AllArgsConstructor
public class Teacher { private int id;
private String name;
}
package com.sxd.test2; import lombok.AllArgsConstructor;
import lombok.Data; @Data
@AllArgsConstructor
public class Student implements Cloneable{
private int id;
private String name;
private Teacher teacher; @Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
package com.sxd.test2; import org.junit.Test; public class DataTest { @Test
public void test() throws CloneNotSupportedException {
Student s1 = new Student(1,"小明",new Teacher(1,"张老师"));
Student s2 = (Student) s1.clone();
System.out.println(s1 ==s2);
System.out.println(s1.getName()+"《》《》《》"+s2.getName());
s2.setName("小张");
System.out.println(s1.getName()+"《》《》《》"+s2.getName());
System.out.println(s1.getTeacher() +"《》《》《》"+ s2.getTeacher());
Teacher teacher = s1.getTeacher();
teacher.setName("王老师");
System.out.println(s1.getTeacher() +"《》《》《》"+ s2.getTeacher()); }
}
1》Object中的clone()方法,提供的是浅克隆,且必须要实现Cloneable接口,否则会抛异常。
2》要实现深克隆的话,有三种方式
2.1》就是在student重写clone()方法,teacher作为student的一个引用对象属性,也要实现Cloneable接口, 重写clone()方法。
不足:如果teacher中又有引用对象属性,那就要一层一层都要做这样的事情。
2.2》通过序列化和反序列化实现深度克隆,所有相关类只要实现Serializable接口,然后把要克隆的对象写入流中,再从流中将该对象读取出来,就可以重建对象,实现深度克隆。
相关代码:
package com.sxd.test2; import lombok.AllArgsConstructor;
import lombok.Data; import java.io.Serializable; @Data
@AllArgsConstructor
public class Teacher implements Serializable{ private int id;
private String name;
}
package com.sxd.test2; import lombok.AllArgsConstructor;
import lombok.Data; import java.io.*; @Data
@AllArgsConstructor
public class Student implements Serializable{
private int id;
private String name;
private Teacher teacher; public Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(outputStream);
oos.writeObject(this); ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
ObjectInputStream ois = new ObjectInputStream(inputStream); return ois.readObject();
}
}
package com.sxd.test2; import org.junit.Test; import java.io.IOException; public class DataTest { @Test
public void test() throws IOException, ClassNotFoundException {
Student s1 = new Student(1,"小明",new Teacher(1,"张老师"));
Student s2 = (Student) s1.deepClone();
System.out.println(s1 ==s2);
System.out.println(s1.getName()+"《》《》《》"+s2.getName());
s2.setName("小张");
System.out.println(s1.getName()+"《》《》《》"+s2.getName());
System.out.println(s1.getTeacher() +"《》《》《》"+ s2.getTeacher());
Teacher teacher = s1.getTeacher();
teacher.setName("王老师");
System.out.println(s1.getTeacher() +"《》《》《》"+ s2.getTeacher()); }
}
2.3》JSON转化
相关代码:
package com.sxd.test2; import lombok.AllArgsConstructor;
import lombok.Data; @Data
@AllArgsConstructor
public class Teacher{ private int id;
private String name;
}
package com.sxd.test2; import com.google.gson.Gson;
import lombok.AllArgsConstructor;
import lombok.Data; @Data
@AllArgsConstructor
public class Student{
private int id;
private String name;
private Teacher teacher; public Student deepClone2(){
Gson gson = new Gson();
String json = gson.toJson(this);
return gson.fromJson(json,this.getClass()); }
}
package com.sxd.test2; import org.junit.Test; import java.io.IOException; public class DataTest { @Test
public void test() throws IOException, ClassNotFoundException {
Student s1 = new Student(1,"小明",new Teacher(1,"张老师"));
Student s2 = (Student) s1.deepClone2();
System.out.println(s1 ==s2);
System.out.println(s1.getName()+"《》《》《》"+s2.getName());
s2.setName("小张");
System.out.println(s1.getName()+"《》《》《》"+s2.getName());
System.out.println(s1.getTeacher() +"《》《》《》"+ s2.getTeacher());
Teacher teacher = s1.getTeacher();
teacher.setName("王老师");
System.out.println(s1.getTeacher() +"《》《》《》"+ s2.getTeacher()); }
}
====================================================================
4.final、finally、finalize()的区别
1》final 修饰符 类是终极类,不能被继承/方法是最终方法,不能被重写/属性是常量,不能被改变
2》finally 异常处理清除块,无论如何都会被执行
3》finalize() Object的方法,java技术允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。
====================================================================
5.getClass()反射机制
5.1》
1)a.getClass()获得对象运行时类型类,是运行时
2)A.class获取一个类的类型类,是编译时就决定了的
代码:
package com.sxd.test2; import org.junit.Test; public class DataTest { class A{ } class B extends A{ } @Test
public void test() {
A a = new A();
B b = new B();
A ab = new B(); System.out.println(a.getClass()+" "+A.class);
System.out.println(b.getClass()+" "+B.class);
System.out.println(ab.getClass());
ab = a;
System.out.println(ab.getClass());
}
}
5.2》Class.forName()和ClassLoader.loadClass区别【参考:https://www.cnblogs.com/zabulon/p/5826610.html】
Class.forName(className)方法,内部实际调用的方法是 Class.forName(className,true,classloader); 第2个boolean参数表示类是否需要初始化, Class.forName(className)默认是需要初始化。 一旦初始化,就会触发目标对象的 static块代码执行,static参数也也会被再次初始化。 ClassLoader.loadClass(className)方法,内部实际调用的方法是 ClassLoader.loadClass(className,false); 第2个 boolean参数,表示目标对象是否进行链接,false表示不进行链接,由上面介绍可以, 不进行链接意味着不进行包括初始化等一些列步骤,那么静态块和静态对象就不会得到执行
5.3》ClassLoad java类加载器
参考:https://blog.csdn.net/slim68/article/details/70849101
http://www.cnblogs.com/sxdcgaq8080/p/8834248.html
第一,java默认提供的3个ClassLoader以及加载顺序,分别的作用
类的生命周期,就是从类的加载到类实例的创建与使用,再到类对象不再被使用时可以被GC卸载回收。这里要注意一点,由java虚拟机自带的三种类加载器加载的类在虚拟机的整个生命周期中是不会被卸载的,只有用户自定义的类加载器所加载的类才可以被卸载。
第二,双亲委派模型是什么,
每一个ClassLoader都有一个父类加载器,是包含关系,不是继承关系!当一个ClassLoader需要加载一类时,会先交给BootstrapClassLoader试图加载,如果没加载到,则交给扩展加载类,下来是App加载类,一层一层,父级向下,如果所有父级都没加载到,则返回给自己进行加载,如果依旧没有,则报ClassNotFoundException.
特别强调:双亲,不是说真的父亲母亲的双亲,而是parents,父级一级一级向下顺序,加载class的过程!
第三,使用双亲委派模型的好处,
一句话概述:使用双亲委派模型,就是为了防止内存中出现多份相同的字节码!
简要描述:如果没有双亲委派模型,那一个类可以由多个ClassLoader加载到内存中,内存中出现多个不同的这个类。那怎么判断这些类是同一个类呢?通过类名?显然不行,所以不采用双亲委派模型,那么类在内存中的唯一性,将无法保证!
第四,JVM搜索类时,如何判断两个class是相同的?
a.类名相同;b.是由同一个类加载器加载
否则,相互转化,会报ClassCaseException
===================================================================
6.重写equals()方法就一定要重写hashCode()方法,为什么
1》Object中hashCode()是本地方法,返回的就是引用地址,equals()是比较两个对象的引用地址是否相等。所以在object中两个是一致的
2》自定义对象,对象的某个属性相等就认定两个对象相等。这个是你重写equals()方法实现的,但是如果不重写hashCode()方法,显然,两个对象的hashCode是不一致的,违反了java中对【两个对象equals比较相等,那他们的hashCode比较也一定相等的原则】。
3》在使用上,例如:a.equals(b)但是a.hashCode != b.hashCode。那么hashMap.put(a,1),hashMap.get(b) ==1 却不一定相等。因为在hashMap中进行put和get操作都是要根据对象a和b的hashCode值进行定位操作,但是a.hashCode != b.hashCode 所以会出现这样的问题。
所以重写equals方法就尽量要重写hashCode方法!!
===================================================================
7.toString()方法在String中是否被重写了【了解】
1》String中的toString()方法就是 return this;
2》Object中的toString()方法是返回运行时类型类名+hashCode码
===================================================================
8.wait() notify() notifyAll()方法等多线程详见第九篇
http://www.cnblogs.com/sxdcgaq8080/p/8549799.html
===================================================================
9.jdk8有哪些新特性
参考地址:http://www.runoob.com/java/java8-new-features.html
1》Lambda表达式
Lambda表达式,允许函数作为方法的参数传递
代码例如:【将函数作为参数传入方法,优雅】
package com.sxd.test2; public interface Operator {
int operation(int a,int b);
}
package com.sxd.test2; public class OperatorImpl {
static Operator add = (int a,int b) ->a+b;
static Operator less = (a,b) -> a-b;
static Operator multiply = (int a,int b) ->{return a*b;};
static Operator division = (int a, int b) -> a/b;
}
package com.sxd.test2; import org.junit.Test; public class DataTest { private int operate(int a,int b,Operator op){
return op.operation(a,b);
} @Test
public void test() {
System.out.println(operate(3,2,OperatorImpl.add));
System.out.println(operate(3,2,OperatorImpl.less));
System.out.println(operate(3,2,OperatorImpl.multiply));
System.out.println(operate(3,2,OperatorImpl.division)); }
}
2》Stream--集合的高级迭代器,可以串行或并行对集合进行各种操作和汇聚,得到一个新的结果。http://www.cnblogs.com/sxdcgaq8080/p/7383215.html
3》时间日期API http://www.cnblogs.com/sxdcgaq8080/p/7193274.html
4》在Java 8中,Base64编码已经成为Java类库的标准,Base64工具类提供了一套静态方法。http://www.runoob.com/java/java8-base64.html
===================================================================
【面试 JDK】【第一篇】Object类面试详解的更多相关文章
- 11-02 Java Object类使用详解
Object 作为超类 Object是类层次结构的根类,所有的类都直接或者间接的继承自Object类. Object类的构造方法有一个,并且是无参构造,这其实就是理解当时我们说过,子类构造方法默认访 ...
- [转载] Java高新技术第一篇:类加载器详解
本文转载自: http://blog.csdn.net/jiangwei0910410003/article/details/17733153 首先来了解一下字节码和class文件的区别: 我们知道, ...
- Java高新技术第一篇:类加载器详解
首先来了解一下字节码和class文件的区别: 我们知道,新建一个Java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的 ...
- java Object类源代码详解 及native (转自 http://blog.csdn.net/sjw890821sjw/article/details/8058843)
package java.lang; public class Object { /* 一个本地方法,具体是用C(C++)在DLL中实现的,然后通过JNI调用.*/ private static na ...
- 第一篇:Git操作详解
最近由于项目的需要,我需要负责整个项目的托管,其中涉及到很多Git相关的命令,所以就将之前用到的git相关的命令做了一个总结和归纳.由于开发环境是Linux,所以我接下来的操作命令均针对Linux环境 ...
- 【原创】JDK 9-17新功能30分钟详解-语法篇-var
JDK 9-17新功能30分钟详解-语法篇-var 介绍 JDK 10 JDK 10新增了新的关键字--var,官方文档说作用是: Enhance the Java Language to exten ...
- 《手把手教你》系列基础篇(九十七)-java+ selenium自动化测试-框架设计篇-Selenium方法的二次封装和页面基类(详解教程)
1.简介 上一篇宏哥介绍了如何设计支持不同浏览器测试,宏哥的方法就是通过来切换配置文件设置的浏览器名称的值,来确定启动什么浏览器进行脚本测试.宏哥将这个叫做浏览器引擎类.这个类负责获取浏览器类型和启动 ...
- Java类文件结构详解
概述: Class文件结构是了解虚拟机的重要基础之一,如果想深入的了解虚拟机,Class文件结构是不能不了解的.Class文件是一组以8位字节为基础单位的二进制流,各项数据项目严格按照顺序紧凑地排列在 ...
- Farseer.net轻量级开源框架 入门篇:添加数据详解
导航 目 录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 入门篇: 分类逻辑层 下一篇:Farseer.net轻量级开源框架 入门篇: 修改数据详解 ...
- 在java poi导入Excel通用工具类示例详解
转: 在java poi导入Excel通用工具类示例详解 更新时间:2017年09月10日 14:21:36 作者:daochuwenziyao 我要评论 这篇文章主要给大家介绍了关于在j ...
随机推荐
- Windows平台下使用vs code搭建python3环境(1)
前言:最近几周在使用python开发的过程中,碰到了好多坑,由于以前使用visual studio 2015习惯了,导致刚开始搭建python开发环境以及管理各种包的时候有点不习惯,再加上python ...
- 【Java_基础】JVM内存模型与垃圾回收机制
1. JVM内存模型 Java虚拟机在程序执行过程会把jvm的内存分为若干个不同的数据区域来管理,这些区域有自己的用途,以及创建和销毁时间. JVM内存模型如下图所示 1.1 程序计数器 程序计数器( ...
- ps命令查看子进程
[root@centos7 log]# ps -f -e -o pid,ppid,pgid,comm PID PPID PGID COMMAND 5070 5068 5070 bash 7169 50 ...
- perl学习之内置变量
Perl内置特殊变量 一.正则表达式特殊变量:1.$n :包含上次模式匹配的第n个子串2.$& :前一次成功模式匹配的字符串3.$` :前次匹配成功的子串之前的内容4.$’ :前次匹配 ...
- perl学习一:探索Perl世界
1.perl4种变量 scalar: $ 纯变量,标量array: @hash: %file: 大写 2.变量组成 1.命名规则 大小写敏感 . 字母数字下划线...2.无关键字,$+其他,但不可以与 ...
- python插件,pycharm基本用法,markdown文本编写,jupyter notebook的基本操作汇总
5.14自我总结 一.python插件插件相关技巧汇总 安装在cmd上运行 #比如安装 安装:wxpy模块(支持 Python 3.4-3.+ 以及 2.7 版本):pip3 install wxpy ...
- 数据结构( Pyhon 语言描述 ) — — 第5章:接口、实现和多态
接口 接口是软件资源用户可用的一组操作 接口中的内容是函数头和方法头,以及它们的文档 设计良好的软件系统会将接口与其实现分隔开来 多态 多态是在两个或多个类的实现中使用相同的运算符号.函数名或方法.多 ...
- (转)iOS 最佳实践
本文转自http://www.jianshu.com/p/b0bf2368fb95 感谢作者和译者 iOS最佳实践 iOS最佳实践 译者注 本文翻译自 futurice 公司的 iOS Good Pr ...
- c++ 快速幂 代码实现
懒得打代码系列… 不过这个代码挺短的死背下来也ok 解析在最下面 建议自己手动试个数据理解一下 比如 3^5 ^^ 原理:a ^ b = a ^ (b / 2) * 2 (b是奇数的话还要再乘一个a) ...
- C++基本数据类型占字节数
32位编译器 char :1个字节char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节.同理64位编译器)short int : 2个字节int: 4个 ...