三门峡市建设局网站,网页服务器价格,制作手机网页软件,wordpress设置权限设置方法JavaSE八股文 - 面试宝典 一个合格的 计算机打工人 #xff0c;收藏夹里必须有一份 JAVA八股文面试题 #xff0c;特别是即将找工作的计算机人#xff0c;希望本篇博客对你有帮助#xff01; 本文参考了诸多大佬的面试题帖子#xff0c;ps#xff1a;白大锅、哪吒、英雄…JavaSE八股文 - 面试宝典 一个合格的 计算机打工人 收藏夹里必须有一份 JAVA八股文面试题 特别是即将找工作的计算机人希望本篇博客对你有帮助 本文参考了诸多大佬的面试题帖子ps白大锅、哪吒、英雄哪里出来 。都是牛逼级别的存在大家也可以去关注一手学习进步 后续随着自己的学习也会陆续补充新的面试题如果对大家起到帮助的话求赞 、求收藏、求关注 chapter01 Java语言
01. 简述Java语言的特点 1、纯面向对象语言能够直接反应现实生活中的对象 2、平台无关性。 Java利用Java虚拟机运行字节码无论在哪个操作系统上对java程序进行编译编译后的程序可在其他平台上运行 3、解释性语言。编译器把java代码编译成平台无关的之间代码然后在JVM上解释运行具有很好的可移植性 4、安全性和健壮性。Java提供了异常处理和垃圾回收机制去除了C中难以理解的指针特性 5、Java提供了很多内置类库多线程、网络通信还有对WEB应用开发的支持 02. 简述面向对象的三大特性 面向对象编程 是利用 类和对象 编程一种思想。 万物可归类 类是对于世界事物的高度抽象不同的事物之间有不同的关系一个类自身与外界的封装关系一个父类和子类的继承关系一个类和多个类的多态关系…… 万物皆对象 对象是具体的世界事物面向对象的三大特征封装、继承、多态 封装说明一个类行为和属性与其他类的关系低耦合高内聚 继承是父类和子类层次的关系 多态是类和类层次的关系 封装 将客观对象抽象成类封装隐藏了类的内部实现机制可以在不影响使用的情况下改变类的内部结构同时也保护了数据 对外界而已它的内部细节是隐藏的暴露给外界的只是它的访问方法 属性的封装使用者只能通过事先定制好的方法来访问数据可以方便地加入逻辑控制限制对属性的 不合理操作 方法的封装使用者按照既定的方式调用方法不必关心方法的内部实现便于使用 便于修改增强代码的可维护性 继承 继承是从已有的类中派生出新的类新的类能吸收已有类的数据属性和行为并能扩展新的功能使之更适合特殊的需求 在本质上是特殊到一般的关系即常说的is-a关系。 子类继承父类表明子类是一种特殊的父类并且具有父类所不具有的一些属性或方法。从多种实现类中抽象出一个基类使其 具备多种实现类的共同特性当实现类用extends关键字继承了基类父类后实现类就具备了这些相同的属性。父类中通过 private定义的变量和方法不会被继承不能在子类中直接操作父类通过private定义的变量以及方法。 多态 相比于封装和继承Java多态是三大特性中比较难的一个封装和继承最后归结于多态 多态指的是类和类的关系两个类由于继承关系存在有方法的重写故而可以在调用时有父类引用指向子类对象 多态必备三个要素继承重写父类引用指向子类对象。 03. 简述面向对象和面向过程的区别 面向过程: 是分析解决问题的步骤然后用函数把这些步骤—步一步地实现然后在使用的时候——调用则可。性能较高所以 单片机、嵌入式开发等—般采用面向过程开发 面向对象: 是把构成问题的事务分解成各个对象而建立对象的目的也不是为了完成一个个步骤而是为了描述某个事物在解决 整个问题的过程中所发生的行为。面向对象有封装、继承、多态的特性所以易维护、易复用、易扩展。可以设计出低耦合的系 统。但是性能上来说比面向过程要低。 04. 简述JDK和JRE的区别 JDKJava开发工具包(Java Development Kit)提供了Java的开发环境和运行环境。 JREJava运行环境(Java Runtime Environment)提供了Java运行所需的环境。 JDK中包含JREJDK中有一个jre的目录里面包含两个文件夹bin和libbin就是JVMlib就是JVM工作所需要的类库.
如果只运行Java程序安装JRE即可。要编写Java程序需安装JDK. 05. 简述字节序定义以及Java属于哪种字节序 字节序是指多字节数据在计算机内存中存储或网络传输时个字节的存储顺序 通常由小端和大端两组方式。 小端:低位字节存放在内存的低地址端高位字节存放在内存的高地址端。大端高位字节存放在内存的低地址端低位字节存放在内存的高地址端。 Java语言的字节序是大端 06. 简述Java虚拟机Java为何被称作是“平台无关的编程语言” Java虚拟机是一个可以执行Java字节码的虚拟机进程。Java源文件被编译成能被Java虚拟机执行的字节码文件。 Java被设计成允许应用程序可以运行在任意的平台而不需要程序员为每一个平台单独重写或者是重新编译。Java虚拟机让这 个变为可能因为它知道底层硬件平台的指令长度和其他特性。 chapter02 零散语法面试题
01. 简述Java代码块执行顺序 1、父类静态代码块只执行一次 2、子类静态代码块只执行一次 3、父类构造代码块 4、父类构造函数 5、子类构造代码块 6、子类构造函数 7、普通代码块 02. 简述构造方法、成员变量初始化以及静态变量三者的初始化顺序 先后顺序静态成员变量、成员变量、构造方法。 详细的先后顺序 父类静态变量、父类静态代码块、子类静态变量、子类静态代码块、父类非静态变量、父类非静态代码块、父类构造函数、子类 非静态变量、子类非静态代码块、子类构造函数。 03. 简述Java访问修饰符
类内部本包子类外部包public✔✔✔✔protected✔✔✔×default✔✔××private✔×××04. 简述接口和抽象类的相同点和区别
1接口 1.接口使用interface修饰 2.接口不能实例化 3.类可以实现多个接口 ① Java8之前接口的方法都是抽象方法省略了public abstract ② Java8之后接口可以定义静态方法静态方法必须有方法体普通方法没有方法体需要被实现 2抽象类 1.抽象类使用abstract修饰 2.抽象类不能被实例化 3.抽象类只能单继承 4.抽象类中包含抽象方法和非抽象方法非抽象方法需要有方法体 如果一个类继承了抽象类 ① 如果实现了所有的抽象方法子类可以不是抽象类 ② 如果没有实现所有的抽象方法子类仍然是抽象类 05. 举例说明什么情况下会更倾向于使用抽象类而不是接口 接口和抽象类都遵循”面向接口而不是实现编码”设计原则它可以增加代码的灵活性可以适应不断变化的需求。 下面有几个点可以帮助你回答这个问题在 Java 中你只能继承一个类但可以实现多个接口。所以一旦你继承了一个类你就 失去了继承其他类的机会了。 接口通常被用来表示附属描述或行为如 Runnable 、 Clonable 、 Serializable 等等因此当你使用抽象类来表示行为时你的类 就不能同时是 Runnable 和 Clonable( 注这里的意思是指如果把 Runnable 等实现为抽象类的情况 ) 因为在 Java 中你不能继承 两个类但当你使用接口时你的类就可以同时拥有多个不同的行为。 在一些对时间要求比较高的应用中倾向于使用抽象类它会比接口稍快一点。如果希望把一系列行为都规范在类继承层次内并 且可以更好地在同一个地方进行编码那么抽象类是一个更好的选择。有时接口和抽象类可以一起使用接口中定义函数而在 抽象类中定义默认的实现。 06. 简述普通类和抽象类的区别 1.抽象不能被实例化 2.抽象类可以有抽象方法只需声明无需实现 3.有抽象方法的类一定是抽象类 4.抽象类的子类必须实现抽象类的所有抽象方法不然子类还是抽象类 5.抽象方法不能声明静态、不能被static、final修饰 07. 简述Java为什么不支持多继承 1、为了程序的结构能够更加清晰从而便于维护。假设Java语言支持多重继承类C继承自类A和类B如果类A和B都有自定义的成 员方法f(),那么当代码中调用类C的f()会产生二义性。 Java语言通过实现多个接口间接支持多重继承接口由于只包含方法定义不能有方法的实现类C继承接口A与接口B时即使 它们都有方法f(),也不能直接调用方法需实现具体的f()方法才能调用不会产生二义性。 2、多重继承会使类型转换、构造方法的调用顺序变得复杂会影响到性能。 08. 简述Java提供的多态机制 Java提供了两种用于多态的机制分为编译时多态和运行时多态分别是重载与覆盖。 编译时多态主要指方法的重载即通过参数列表的不同来区分不同的方法。 运行时多态主要指继承父类和实现接口时可使用父类引用指向子类对象。 重载重载是指同一个类中有多个同名的方法但这些方法有不同的参数在编译期间就可以确定调用哪个方法。覆盖覆盖是指派生类重写基类的方法使用基类指向其子类的实例对象或接口的引用变量指向 其实现类的实例对象在程序调用的运行期根据引用变量所指的具体实例对象调用正在运行的那个 对象的方法即需要到运行期才能确定调用哪个方法。 09. 简述重载与覆盖的区别 覆盖是父类与子类之间的关系是垂直关系重载是同一类中方法之间的关系是水平关系。覆盖只能由一个方法或一对方法产生关系重载是多个方法之间的关系。覆盖要求参数列表相同重载要求参数列表不同。覆盖中调用方法体是根据对象的类型来决定的而重载是根据调用时实参表与形参表来对应选择 方法体。重载方法可以改变返回值的类型覆盖方法不能改变返回值的类型。 10. 简述什么时候用重载什么使用重写 1.重载是多态的集中体现在类中要以统一的方式处理不同类型数据的时候可以使用重载 2.重写的使用是建立在继承关系上的子类在继承父类的基础上增加新的功能可以用重写 3.简单总结 重载是多样性重写是增强剂 目的是提高程序的多样性和健壮性以适配不同场景使用时使用重载进行扩展 目的的是在不修改原方法及源代码的基础上对方法进行扩展或增强时使用重写 4.在里氏代换原则中子类对父类的方法尽量不要重写和重载。可以采用final的手段强制来遵守 设计模式 cgilb实现动态代理核心原理就是方法的重写 详细解答 Java的重载(overload) 最重要的应用场景就是构造器的重载构造器重载后提供多种形参形式的构造器可以应对不同的业务需 求加强程序的健壮性和可扩展性比如我们最近学习的Spring源码中的ClassPathXmlApplicationContext它的构造函数使用重 载一共提供了10个构造函数这样就为业务的选择提供了多选择性。在应用到方法中时主要是为了增强方法的健壮性和可扩展 性比如我们在开发中常用的各种工具类比如我目前工作中的短信工具类SMSUtil, 发短信的方法就会使用重载针对不同业务场 景下的不同形参提供短信发送方法这样提高了工具类的扩展性和健壮性。 总结重载必须要修改方法(构造器)的形参列表可以修改方法的返回值类型也可以修改方法的异常信息即访问权限 使用范围是在同一个类中目的是对方法(构造器)进行功能扩展以应对多业务场景的不同使用需求。提高程序的健壮性和扩展 性。 java的重写(override) 只要用于子类对父类方法的扩展或修改但是在我们开发中为了避免程序混乱重写一般都是为了方法的 扩展比如在cglib方式实现的动态代理中代理类就是继承了目标类对目标类的方法进行重写同时在方法前后进行切面织入。 方法重写时参数列表、返回值的类型不能修改异常可以减少或者删除但是不能抛出新的异常或者更广的异常 方法的权限可以降低限制但是不能做更严格的限制 11. 简述instanceof关键字的作用
instanceof严格来说是Java中的一个双目运算符用来测试一个对象是否为一个类的实例用法为:
boolean result obj instanceof Class 其中obj为一个对象Class表示一个类或者一个接口当obj为Class的对象或者是其直接或间接子类或者是其接口的实现 类结果result都返回true否则返回false。 注意:编译器会检查obj是否能转换成右边的class类型如果不能转换则直接报错如果不能确定类型则通过编译具体看运行 时定。 int i 0;
System.out.println(i instanceof Integer); // 编译不通过 i必须是引用类型不能是基本类型
System.out.println(i instanceof Object); // 编译不通过Integer integer new Integer(1);
System.out.println(integer instanceof Integer); // true// false ,在 JavaSE规范 中对 instanceof 运算符的规定就是如果 obj 为 null那么将返回false。
System.out.println(null instanceof Object);12. 简述final关键字的作用
1用来修饰一个引用 1.如果引用是基本数据类型则该引用为常量在编译阶段会存入常量池该值无法被修改 2.如果引用是引用数据类型比如对象、数组则该对象、数组本身内容可以修改但指向该对象或数组的地址的引用不能修改 3.如果引用时类的成员变量则必须当场赋值否则编译会报错 2用来修饰一个方法 1.当使用final修饰方法时这个方法将成为最终方法无法被子类重写 2.但该方法仍然可以被继承 3.JVM会尝试将其内联以提高运行效率 3用来修饰一个类 1.当用final修饰一个类时该类成为最终类无法被继承 比如String类就是最终类看JDK源码是被final修饰的 除此之外编译器对fianl域要遵守的两个重排规则 在构造函数内对一个final域的写入与随后把这个被构造对象的引用赋值给一个引用变量这两个操作之间不能重排序 初次读一个包含final域的对象的引用与随后初次读这个final域,两个操作之间不能重排序 13. 简述static关键字的作用 static的主要作用有两个 为某种特定数据类型或对象分配与创建对象个数无关的单一的存储空间。使得某个方法或属性与类而不是对象关联在一起即在不创建对象的情况下可通过类直接调用方法 或使用类的属性。 具体而言static又可分为4种使用方式 修饰成员变量。用static关键字修饰的静态变量在内存中只有一个副本。只要静态变量所在的类被加 载这个静态变量就会被分配空间可以使用’‘类.静态变量’‘和’‘对象.静态变量’的方法使用。修饰成员方法。static修饰的方法无需创建对象就可以被调用。static方法中不能使用this和super关 键字不能调用非static方法只能访问所属类的静态成员变量和静态成员方法。修饰代码块。JVM在加载类的时候会执行static代码块。static代码块常用于初始化静态变量。static 代码块只会被执行一次。修饰内部类。static内部类可以不依赖外部类实例对象而被实例化。静态内部类不能与外部类有相同 的名字不能访问普通成员变量只能访问外部类中的静态成员和静态成员方法。 补充
Java中是否可以覆盖(override)一个private或者是static的方法 Java中static方法不能被覆盖因为方法覆盖是基于运行时动态绑定的而static方法是编译时静态绑定的。static方法跟类的任何 实例都不相关所以概念上不适用。 Java中也不可以覆盖private的方法因为private修饰的变量和方法只能在当前类中使用如果是其他的类继承当前类是不能访问 到private变量或方法的当然也不能覆盖。 14. 简述为何不允许从静态方法中访问非静态变量 1.静态变量属于类本身在类加载的时候就会分配内存可以通过类名直接访问 2.非静态变量属于类的对象只有在类的对象产生时才会分配内存通过类的实例去访问 3.静态方法也属于类本身但此时没有类的实例内存中没有非静态变量所以无法调用 15. 简述java中的引用类型
1强引用 Java中默认声明的就是强引用 Object obj new Object();
obj null;只要强引用存在垃圾回收器将永远不会回收被引用的对象内存不足也不会回收。如果想被回收可以将对象置为null 2软引用 在内存足够的时候软引用不会被回收。只有在内存不足时系统才会回收软引用对象 如果回收了软引用对象之后仍然没有足够的内存才会抛出内存溢出异常 使用方式 // 注意wrf这个引用也是强引用它是指向SoftReference这个对象的
// 这里的软引用指的是指向new String(str)的引用也就是SoftReference类中T
SoftReferenceString wrf new SoftReferenceString(new String(str));使用场景 创建缓存的时候创建的对象放进缓存中当内存不足时JVM就会回收早先创建的对象 3弱引用 进行垃圾回收时只要垃圾回收器发现它弱引用就会被回收 使用方式 WeakReferenceString wrf new WeakReferenceString(str);使用场景 Java源码中的java.util.WeakHashMap中的key就是使用弱引用我的理解就是一旦我不需要某个引用JVM会自动 帮我处理它这样我就不需要做其他操作。 4虚引用 虚引用的回收机制跟弱引用差不多但是它被回收之前会被放入ReferenceQueue 中。注意哦其它引用是被JIVM回收 后才被传入ReferenceQueue 中的。由于这个机制所以虚引用大多被用于引用销毁前的处理工作。还有就是虚引用创建的 时候必须带有ReferenceQueue 使用 例子: PhantomReferenceString prf new PhantomReferenceString(new String(str), new ReferenceQueue());可用场景: 对象销毁前的一些操作比如说资源释放等。object.finalize()虽然也可以做这类动作但是这个方式即不安全又低效上 诉所说的几类引用都是指对象本身的引用而不是指Reference的四个子类的引用( SoftReference等)。 5引用队列 引用队列可以与软引用、弱引用、虚引用一起配合使用 当垃圾回收机制准备回收一个对象时如果发现它还有引用时就会在回收对象之前把这个引用加入到引用队列中。 程序可以通过判断引用队列中是否加入了该引用来判断被引用的对象是否将要被垃圾回收这样可以在对象被回收之前一些必要 的措施。 16. 简述Object类常用方法 hashCode通过对象计算出的散列码。用于map型或equals方法。 需要保证同一个对象多次调用该方法总返回相同的整型值。equals判断两个对象是否一致。需保证equals方法相同对应的对象hashCode也相同。toString: 用字符串表示该对象clone:深拷贝一个对象 17. 简述与equals方法的区别 1.对于基本类型 比较的是值 2.对于引用类型 比较的是地址 3.equals 不能比较基本数据类型 4.如果没有重写equalsequals 就相对于 5.如果重写了equals方法equals比较的是对象的内容 牛客网面试题 ① 18. 简述hashcode和作用
Java中的Object对象里的一个方法
public native int hashcode();
(1) hashcode()方法的使用 hashcode()方法主要配合基于散列的集合一起使用比如HashSet、HashMap、HashTable。 当集合需要添加对象时先调用这个对象的hashcode()方法得到对应的hashcode值实际上hashcode中会有一个table保存以及 存进去的对象的hashcode值。如果table中没有该hashcode值则直接存入。 如果有就调用equals方法与新元素进行比较相同就不存了不同就存入。 2equals和hashcode的关系 1.如果equals为truehashcode一定相等 2.如果equals为falsehashcode不一定不相等 3.如果hashcode值相等equals不一定相等 4.如果hashcode值不等equals一定不等 3重写equals方法时一定要重写hashcode方法
4百度百科 hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点例如java.util.Hashtable 提供的哈希表。 hashCode 的常规协定是 在 Java 应用程序执行期间在同一对象上多次调用 hashCode 方法时必须一致地返回相同的整数前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行该整数无需保持一致。 如果根据 equals(Object) 方法两个对象是相等的那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。 以下情况不是必需的如果根据 equals(java.lang.Object) 方法两个对象不相等那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是程序员应该知道为不相等的对象生成不同整数结果可以提高哈希表的性能。 实际上由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。这一般是通过将该对象的内部地址转换成一个整数来实现的但是 JavaTM 编程语言不需要这种实现技巧。 当equals方法被重写时通常有必要重写 hashCode 方法以维护 hashCode 方法的常规协定该协定声明相等对象必须具有相等 的哈希码。 5小白解释 1.hashcode是用来查找的如果你学过数据结构就应该知道在查找和排序这一章有 例如内存中有这样的位置 0 1 2 3 4 5 6 7 而我有个类这个类有个字段叫ID,我要把这个类存放在以上8个位置之一如果不用hashcode而任意存放那么当查找时就需要到 这八个位置里挨个去找或者用二分法一类的算法。 但如果用hashcode那就会使效率提高很多。 我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID8然后把我们的类存放在取得得余数那个位置。比如我们的ID为99除8的余数为1那么我们就把该类存在1这个位置如果ID是13求得的余数是5那么我们就把该类放在5这个位置。这样以后在查找该类时就可以通过ID除 8求余数直接找到存放的位置了。 2.但是如果两个类有相同的hashcode怎么办那我们假设上面的类的ID不是唯一的例如9除以8和17除以8的余数都是1那么这是不是合法的回答是可以这样。那么如何判断呢在这个时候就需要定义 equals了。 也就是说我们先通过 hashcode来判断两个类是否存放某个桶里但这个桶里可能有很多类那么我们就需要再通过 equals 来在这个桶里找到我们要的类。 那么。重写了equals()为什么还要重写hashCode()呢 想想你要在一个桶里找东西你必须先要找到这个桶啊你不通过重写hashcode()来找到桶光重写equals()有什么用啊。 19. 是否存在两个不相等的对象有相同的hashcode
有可能。在产生hash冲突时两个不相等的对象就会有相同的hashcode值当hash冲突产生时般有以下几种方式来处理: **拉链法**每个哈希表节点都有一个next指针,多个哈希表节点可以用next指针构成一个单向链表被分配到同一个索引上的多个节 点可以用这个单向链表进行存储. **开放定址法**一旦发生了冲突,就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入 **再哈希**又叫双哈希法,有多个不同的Hash函数.当发生冲突时,使用第二个,第三个…等哈希函数计算地址,直到无冲突 20. 简述克隆、如何实现、深拷贝和浅拷贝区别
1为什么要使用克隆 想对一个对象进行复制又想保留原有的对象进行接下来的操作这个时候就需要克隆了 2如何实现对象克隆 1.实现Cloneable接口重写clone方法 2.实现Serializable接口通过对象的序列化和反序列化实现克隆可以实现真正的深克隆 3.BeanUtilsapache和Spring都提供了bean工具只是这都是浅克隆 3深克隆和浅克隆区别是什么 浅克隆仅仅克隆基本类似变量不克隆引用类型变量 深克隆即克隆基本类型变量又克隆引用类型变量 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fIMvpovs-1678417682138)(01 JavaSE八股文.assets/image-20220428102117822.png)]
4代码实例
// 后续在补充21. 简述JavaBean的命名规范 1.JavaBean 类必须是一个公共类并将其访问属性设置为 public 2.JavaBean 类必须有一个空的构造函数类中必须有一个不带参数的公用构造器此构造器也应该通过调用各个特性的设置方法 来设置特性的缺省值。 3.一个javaBean类不应有公共实例变量类变量都为private 4.持有值应该通过一组存取方法getXxx 和 setXxx来访问对于每个特性应该有一个带匹配公用 getter 和 setter 方法的专用 实例变量。 属性为布尔类型可以使用 isXxx() 方法代替 getXxx() 方法。 通常属性名是要和 包名、类名、方法名、字段名、常量名作出区别的: 22. JavaBean属性命名规范问题分析
public class User {private String busName;private String pCount;private Boolean isRunning;//正确的命名方式驼峰式的public String getBusName() {return busName;}public void setBusName(String busName) {this.busName busName;}// 这是什么public String getpCount() {return pCount;}public void setpCount(String pCount) {this.pCount pCount;}// 这个也是不允许的public Boolean getIsRunning() {return isRunning;}public void setIsRunning(Boolean isRunning) {this.isRunning isRunning;}
}1.JavaBean属性命名尽量使用常规的驼峰命名规则 2.属性名第一个单词尽量避免只使用一个字母eBook、eName 3.boolean属性名避免使用”is“开头的名称 4.随着JDKEclipseSpring等软件版本的不断提高低版本的出现的问题可能在高版本中解决了低版本原本正常的代码可能在 高版本环境下不再支持。 23. 简述标识符的命名规则 标识符的含义: 是指在程序中我们自己定义的内容譬如类的名字方法名称以及变量名称等等都是标识符。 命名规则:(硬性要求) 标识符可以包含英文字母O-9的数字$以及_ 标识符不能以数字开头 标识符不是关键字 命名规范:(非硬性要求) 类名规范:首字符大写后面每个单词首字母大写(大驼峰式)。 变量名规范:首字母小写后面每个单词首字母大写(小驼峰式)。 方法名规范:同变量名。 24. 简述构造方法、构造方法重载、复制构造方法 当新对象被创建的时候构造方法会被调用。每一个类都有构造方法。在程序员没有给类提供构造方法的情况下Java编译器会 为这个类创建一个默认的构造方法。 Java中构造方法重载和方法重载很相似。可以为一个类创建多个构造方法。每一个构造方法必须有它自己唯一的参数列表。 Java不支持像C中那样的复制构造方法这个不同点是因为如果你不自己写构造方法的情况下Java不会创建默认的复制构造 方法。 25. 简述值传递和引用传递 值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量. 引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。 一般认为,java内的基础类型数据传递都是值传递. java中实例对象的传递是引用传递 26. Comparable和Comparator接口的用途和区别 Java提供了只包含一个compareTo()方法的Comparable接口。这个方法可以个给两个对象排序。具体来说它返回负数0正 数来表明已经存在的对象小于等于大于输入对象。 Java提供了包含compare()和equals()两个方法的Comparator接口。compare()方法用来给两个输入参数排序返回负数0正 数表明第一个参数是小于等于大于第二个参数。equals()方法需要一个对象作为参数它用来决定输入参数是否和comparator 相等。只有当输入参数也是一个comparator并且输入参数和当前comparator的排序结果是相同的时候这个方法才返回true。 chapter03 常用类与内部类
01. 简述Java基本数据类型 byte: 占用1个字节取值范围-128 ~ 127 short: 占用2个字节取值范围-215 ~ 215-1 int占用4个字节取值范围-231 ~ 231-1 long占用8个字节 float占用4个字节 double占用8个字节 char: 占用2个字节 boolean占用大小根据实现虚拟机不同有所差异 基本类型大小字节默认值封装类byte1byte0Byteshort2short0Shortint40Integerlong80LLongfloat4o.ofFloatdouble8o.odDoubleboolean-flaseBooleanchar2\u000(null)Character
注 1.int是基本数据类型Integer是int的封装类是引用类型。int默认值是0而Integer默认值是null所以Integer能区分出0和null 的情况。一旦java看到null就知道这个引用还没有指向某个对象再任何引用使用前必须为其指定一个对象否则会报错。 2.基本数据类型在声明时系统会自动给它分配空间而引用类型声明时只是分配了引用空间必须通过实例化开辟数据空间之后 才可以赋值。数组对象也是一个引用对象将一个数组赋值给另一个数组时只是复制了一个引用所以通过某一个数组所做的修改 在另—个数组中也看的见。 虽然定义了boolean这种数据类型但是只对它提供了非常有限的支持。在Java虚拟机中没有任何供boolean值专用的字节码指 令Java语言表达式所操作的boolean值在编译之后都使用Java虚拟机中的int数据类型来代替而boolean数组将会被编码成 Java虚拟机的byte数组每个元素boolean元素占8位。 这样我们可以得出boolean类型占了单独使用是4个字节在数组中又是1个字节。使用in的原因是对于当下32位的处理器 (CPU)来说一次处理数据是32位(这里不是指的是32/64位系统而是指CPU硬件层面)具有高效存取的特点。 02. 简述自动装箱拆箱 对于Java基本数据类型均对应一个包装类。 装箱就是自动将基本数据类型转换为包装器类型如int-Integer调用方法Integer的valueOf(int)方法 拆箱就是自动将包装器类型转换为基本数据类型如Integer-int调用方法Integer的intValue方法 ①、在Java SE5之前如果要生成一个数值为10的Integer对象必须这样进行
Integer i new Integer(10);而在从Java SE5开始就提供了自动装箱的特性如果要生成一个数值为10的Integer对象只需要这样就可以了 Integer i 10; ② 面试题
下面的代码会输出什么
public class Main {public static void main(String[] args) {Integer i1 100;Integer i2 100;Integer i3 200;Integer i4 200;System.out.println(i1i2);System.out.println(i3i4);}
}// 运行结果
true
false为什么会出现上述这样的结果呢 输出结果表面i1和i2指向的是同一个对象而i3和i4指向的不是同一个对象。 此时只需要看一下源码便知究竟下面是Integer的valueOf(int)方法的具体实现 public static Integer valueOf(int i) {if(i -128 i IntegerCache.high)return IntegerCache.cache[i 128];elsereturn new Integer(i);
} 其中IntegerCache的实现为 private static class IntegerCache {static final int high;static final Integer cache[];static {final int low -128;// high value may be configured by propertyint h 127;if (integerCacheHighPropValue ! null) {// Use Long.decode here to avoid invoking methods that// require Integers autoboxing cache to be initializedint i Long.decode(integerCacheHighPropValue).intValue();i Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh Math.min(i, Integer.MAX_VALUE - -low);}high h;cache new Integer[(high - low) 1];int j low;for(int k 0; k cache.length; k)cache[k] new Integer(j);
}private IntegerCache() {}
} 从这2段代码可以看出在通过valueof方法创建Integer对象的时候如果数值在[-128,127]之间便返回指向 IntegerCache.cache 中已经存在的对象的引用;否则创建—个新的Integer对象。 上面的代码中i⑴和i2的数值为100因此会直接从cache中取已经存在的对象所以1和i2指向的是同一个对象而i3和i4则是分 别指向不同的对象。 面试题2以下代码输出什么?
public class Main {public static void main(String[] args) {Double i1 100.0;Double i2 100.0;Double i3 200.0;Double i4 200.0;System.out.println(i1i2);System.out.println(i3i4);}
}// 输出结果
false
false原因在某个范围内的整形数值的个数是有限的而浮点数却不是牛客网关于自动装箱的面试题 03. byte类型1271等于多少 byte的范围是-128~127。 字节长度为8位最左边的是符号位而127的二进制为01111111所以执行1操作时01111111变为10000000。 大家知道计算机中存储负数存的是补码的兴衰。左边第一位为符号位。 那么负数的补码转换成十进制如下 一个数如果为正则它的原码、反码、补码相同一个正数的补码将其转化为十进制可以直接转换。 已知一个负数的补码将其转换为十进制数步骤如下 先对各位取反 将其转换为十进制数 加上负号再减去1 例如10000000最高位是1是负数①对各位取反得01111111转换为十进制就是127加上负号得-127再减去1得-128 04. 1.3 * 0.1 0.3 的返回值是什么 false因为浮点数不能完全精确的表示出来 05. 简述 aab 与 ab 的区别 操作符会进行隐式自动类型转换此处ab隐式的将加操作的结果类型强制转换为持有结果的类型 aab则不会自动进行类型转换 byte a 127;
byte b 127;
b a b; // 报编译错误:cannot convert from int to byte
b a;以下代码是否有错有的话怎么改
short s1 1;
s1 s1 1;// 有错误. short类型在进行运算时会自动提升为int类型也就是说s11的运算结果是int类型而s1是short类型此时编译器会报错.正确写法
short s1 1;
s1 1;// 操作符会对右边的表达式结果强转匹配左边的数据类型所以没错10. String属于基本数据类型吗 答 1.不属于 2.八大基本数据类型byte、short、char、int、long、float、double、boolean 11. String str“i” 与 String str new String(“i”) 一样吗 1.String str “i”; 会将其分配到常量池中常量池中没有重复的元素。如果常量池中存在i就将i的地址赋给变量如果没有就创建 一个再赋值给变量 2.String str new String(“i”); 会将对象分配给堆中即使内存一样还是会创建一个新的对象 12. new String(“a”) new String(“b”)会创建几个对象
Java intern函数详解 对象1new StringBuilder() 对象2new String(“a”) 对象3常量池中的“a” 对象4new String(“b”) 对象5常量池中的“b” 深入刨析StringBuilder中的toString(): 对象6new String(“ab”) 强调一下toString的调用在字符串常量池中没有生成“ab 附加题
String s1 new String(1) new String(1); // s1变量记录的地址为new Strings1.intern(); // 在字符串常量池中生成11。
// 如何理解
// jdk6创建了一个新的对象11也就有新的地址
// jdk7此时常量池中并没有创建11而是创建了一个指向堆空间中new String(11)的地址String s2 11;System.out.println(s1 s2); // jdk6:false; jdk7:true13. 简述如何将字符串反转 将对象封装到StringBuilder中调用reverse方法反转 package com.clz.java;public class ReverseString {public static void main(String[] args) {String str Hello World!;StringBuilder stringBuilder new StringBuilder(str);String ret stringBuilder.reverse().toString();System.out.println(ret);}
}14. Java 中操作字符串都有哪些类它们之间有什么区别
1String String是只读字符串它并不是基本数据类型而是一个对象。从底层源码来看是一个final类型的字符数组所引用的 字符串不能被改变一经定义无法在增删改。 private final char value[]; 如果对String类型对象修改需要新建对象将老字符和新增加的字符一并存进去。 每次操作隐形在堆山newl一个跟原字符串相同的StringBuilder对象在调用append方法拼接字符串。 StringBuilder和StringBuffer它们两都继承了AbstractStringBuilder抽象类
/*** The value is used for character storage.*/
char[] value; // 可变数组2StringBuilder StringBuilder采用无final修饰的字符数组进行保存因此可变 线程不安全效率高多用于单线程 3StringBuffer StringBuffer采用无final修饰的字符数组进行保存可理解为实现线程安全的StringBuilder。 线程安全由于加锁的原因效率不如StringBuilder多用于多线程 不频繁的字符串操作使用String操作频繁的情况不建议使用String StringBuilder StringBuffer String 15. 为什么要把String设计为不变量 节省空间字符串常量存储在JVM的字符串池中可以被用户共享。提高效率:String会被不同线程共享是线程安全的。在涉及多线程操作中不需要同步操作。安全String常被用于用户名、密码、文件名等使用由于其不可变可避免黑客行为对其恶意修改。 16. 简述内部类及其作用 成员内部类作为成员对象的内部类。可以访问private及以上外部类的属性和方法。外部类想要访问内部类属性或方法时必须要 创建一个内部类对象然后通过该对象访问内部类的属性或方法。外部类也可访问private修饰的内部类属性。 局部内部类存在于方法中的内部类。访问权限类似局部变量只能访问外部类的final变量。 匿名内部类只能使用一次没有类名只能访问外部类的final变量。 静态内部类类似类的静态成员变量。 17. 类的访问权限面试题 18. 关于包权限的描述面试题 chapter04 异常
01. 简述Java异常的分类 Java异常分为Error程序无法处理的错误Exception程序本身可以处理的异常这两个类均继承Throwable Error常见的有StackOverFlowError、OutOfMemoryError等 Exception可分为 运行时异常 和 非运行时异常 对于运行时异常可以利用 try~catch 的方式进行处理也可以不处理 对于编译时异常必须处理不处理的话程序无法通过编译 02. 简述throw和throws的区别 作用位置 throw在方法体内部throws在方法签名处、声明处 作用对象 throw抛出具体异常对象throws声明可能抛出异常的异常类型 作用效果 throw每次只能抛出一个异常对象源头制造异常throws代表该方法可能会抛出的异常列表提醒调用者 03. 简述final、finally、finalize的区别 final 用于声明属性、方法和类分别表示属性不可变、方法不可覆盖、类不可继承 finally 用于抛异常finally代码块内语句无论是否发生异常都会在执行finally常用于一些流的关闭。 finalize方法用于垃圾回收。 一般情况下不需要我们实现 finalize当对象被回收的时候需要释放一些资源比如socket链接在对象初始化时创建整个生命周期内有效那么需要实现 finalize 方法关闭这个链接。 但是当调用finalize方法后并不意味着gc会立即回收该对象所以有可能真正调用的时候对象又不需要回收了然后到了真正要回收的时候因为之前调用过一次这次又不会调用了产生问题。所以不推荐使用finalize方法。 04. try 中 return 了finally 还会执行吗 会执行并且finally的执行早于try里面return 结论 ① 不管有木有出现异常finally块中代码都会执行② 当 try 和 catch 中有 return 时finally 仍然会执行③ finally 是在 return 后面的表达式运算后执行的 (此时并没有返回运算后的值而是先把要返回的值保存起来管 finally中的代码怎么样返回的值都不会改变任然是之前保存的值)所以函数返回值是在 finally 执行前确定的 ④ finally 中最好不要包含 return否则程序会提前退出返回值不是 try 或 catch 中保存的返回值 05. finally代码块是否一定会执行 当遇到下面情况不会执行。 ① 当程序在进入try语句块之前就出现异常时会直接结束。 ② 当程序在try块中强制退出时如使用 System.exit(0)也不会执行finally块中的代码。 其它情况下在try/catch/finally语句执行的时候try块先执行 当有异常发生catch和finally进行处理后程序就结束了 当没有异常发生在执行完finally中的代码后后面代码会继续执行。 值得注意的是当try/catch语句块中有return时finally语句块中的代码会在return之前执行。 如果try/catch/finally块中都有return语句finally块中的return语句会覆盖try/catch模块中的return语句。 06. 简述常见的异常类 1.NullPointerException空指针异常 2.SQLException数据库相关的异常 3.IndexOutOfBoundsException数组下角标越界异常 4.FileNotFoundException打开文件失败时抛出 5.IOException当发生某种IO异常时抛出 6.ClassCastException当试图将对象强制转换为不是实例的子类时抛出此异常 7.NoSuchMethodException无法找到某一方法时抛出 8.ArrayStoreException试图将错误类型的对象存储到一个对象数组时抛出的异常 9.NumberFormatException当试图将字符串转换成数字时失败了抛出 10.IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。 11.ArithmeticException当出现异常的运算条件时抛出此异常。例如一个整数“除以零”时抛出此类的一个实例。 07. 自定义异常在生产中如何应用 Java虽然提供了丰富的异常处理类但是在项目中还会经常使用自定义异常其主要原因是Java提供的异常类在某些情况下还 是不能满足实际需球。 例如以下情况 ① 系统中有些错误是符合Java语法但不符合业务逻辑。 ② 在分层的软件结构中通常是在表现层统一对系统其他层次的异常进行捕获处理。 chapter05 集合与泛型
01. 简述泛型 泛型即 “参数化类型”解决不确定对象具体类型的问题在编译阶段有效。 在泛型使用过程中操作的数据类型被指定为一个参数这个参数类型在类中称为泛型类、接口中称为泛型接口、方法中称为泛 型方法。 泛型是Java SE1.5之后的特性《Java 核心技术》中对泛型的定义是 “泛型”意味着编写的代码可以被不同类型的对象所重用 “泛型”顾名思义“泛指的类型”。我们提供了泛指的概念但具体执行的时候却可以有具体的规则来约束比如我们用的非常多的
ArrayList就是个泛型类ArrayList作为集合可以存放各种元素如Iteger、String自定义的各种类型等。但在我们使用的使用通
过具体的规则来约束如我们可以约束集合中只存放Integer类型的元素如
ListInteger iniData new ArrayList();使用泛型的好处 以集合来举例使用泛型的好处是我们不必因为添加元素类型的不同而定义不同类型的集合如整型集合类浮点型集合类字符串集合类我们可以定义一个集合来存放整型、浮点型字符串型数据而这并不是最重要的因为我们只要把底层存储设置了 Object即可添加的数据全部都可向上转型为Object。更重要的是我们可以通过规则按照自己的想法控制存储的数据类型。 02. 简述泛型擦除 Java编译器生成的字节码是不包含泛型信息的泛型类型信息将在编译处理是被擦除这个过程被称为泛型擦除。 03. 简述Java容器种类
Collection继承结构图 Map结构图 04. 简述Collection和Collections的区别 1.Collection是最基本的集合接口Collection派生了两个子接口list和set分别定义了两种不同的存储方式 2.Colleections是包装类集合工具类它包含各种有关集合操作的静态方法对集合的搜索、排序、线程安全化等 此类不能实例化就像一个工具类服务于Collection框架。 05. 简述Java的List List是一个有序队列在JAVA中有两种实现方式 ① ArrayList 使用数组实现是容量可变的非线程安全列表随机访问快集合扩容时会创建更大的数组把原有数组复制到新数组。② LinkedList 本质是双向链表与 ArrayList 相比插入和删除速度更快但随机访问元素很慢。 06. 简述ArrayList、LinkedList和Vector的共同点与区别 ① ArrayList、Vector 和 LinkedList 都是可以 动态改变长度的数组。 ② ArrayList和Vector都是基于存储元素的 Object[] array来实现的 它们会在内存中开辟一块连续的空间来存储支持下标、索引访问。 但在涉及插入元素时可能需要移动容器中的元素插入效率较低。 当存储元素超过容器的初始化容量大小ArrayList与Vector均会进行扩容。 ③ LinkedList采用双向列表实现对数据索引需要从头开始遍历因此随机访问效率较低 但在插入元素的时候不需要对数据进行移动插入效率较高。 ④ Vector是线程安全的其大部分方法是直接或间接同步的。 ArrayList不是线程安全的其方法不具有同步性质。LinkedList也不是线程安全的。 07. 简述Java的Set Set 即集合该数据结构不允许元素重复且无序。JAVA对Set有三种实现方式 ① HashSet 通过 HashMap 实现HashMap 的 Key 即 HashSet 存储的元素Value系统自定义一个名为 PRESENT 的 Object 类型常量。判断元素是否相同时先比较hashCode相同后再利用equals比较查询 O(1) ② LinkedHashSet 继承自 HashSet通过 LinkedHashMap 实现使用双向链表维护元素插入顺序。 ③ TreeSet 通过 TreeMap 实现的底层数据结构是红黑树添加元素到集合时按照比较规则将其插入合适的位置保证插入后的集合仍然有序。查询 O(logn) 08. 简述HashSet中equals与hashCode的关系 equals和hashCode这两个方法都是从object类中继承过来的equals主要用于判断对象的内存地址引用是否是同一个地址 hashCode根据定义的哈希规则将对象的内存地址转换为一个哈希码。 HashSet中存储的元素是不能重复的主要通过hashCode与equals两个方法来判断存储的对象是否相同 如果两个对象的hashCode值不同说明两个对象不相同。如果两个对象的hashCode值相同接着会调用对象的equals方法如果equlas方法的返回结果为true那么说明两个对象相同否则不相同。 09. 简述java的TreeMap TreeMap 是底层利用红黑树实现的Map结构底层实现是一棵平衡的排序二叉树由于红黑树的插入、删除、遍历时间复杂度都为O(logN)所以性能上低于哈希表。 但是哈希表无法提供键值对的有序输出红黑树可以按照键的值的大小有序输出。 10. 简述JAVA的HashMapJDK1.7与1.8的区别 JDK8 之前底层实现是数组 链表JDK8 改为数组 链表/红黑树。主要成员变量包括存储数据的table 数组、元素数量 size、 加载因子 loadFactor。 HashMap 中数据以键值对的形式存在键对应的 hash 值用来计算数组下标如果两个元素 key 的hash 值一样就会发生哈希 冲突被放到同一个链表上。 table 数组记录 HashMap 的数据每个下标对应一条链表所有哈希冲突的数据都会被存放到同一条链表Node/Entry 节点包 含四个成员变量key、value、next 指针和 hash 值。在JDK8后链表超过8会转化为红黑树。 若当前数据/总数据容量负载因子Hashmap将执行扩容操作。 默认初始化容量为 16扩容容量必须是 2 的幂次方、最大容量为 1 30 、默认加载因子为 0.75。 11. 简述HashMap和HashTable的区别 1.HashMap是线程不安全的HashTable是线程安全的在多线程访问HashMap需要提供额外的同步机制。 2.HashMap是Hashtable的轻量级实现HashMap中运行键和值为null最多一个key为nullHashTable不允许 3.HashTable的默认容量是16以2的倍数扩容HashTable是11以2*n1扩容扩容因子0.75 4.Hashtable使用Enumeration进行遍历HashMap使用Iterator进行遍历。 12. 简述何时使用HashMap、TreeMap 如果对Map进行插入、删除或定位一个元素的操作更频繁HashMap是更好的选择。 如果需要对key集合进行有序的遍历TreeMap是更好的选择。 13. 简述下List、Set、Map三种的区别 List(对付顺序的好帮手)List接口存储一组不唯一(可以有多个元素引用相同的对象)有序的对象 Set(注重独—无二的性质)不允许重复的集合。不会有多个元素引用相同的对象。 Map(用Key来搜索的专家)使用键值对存储。Map会维护与Key有关联的值。两个Key可以引用相同的对象但Key不能重 复典型的Key是String类型但也可以是任何对象。 15. 简述Java中线程安全的数据结构 HashTable 哈希表的线程安全版效率低 ConcurrentHashMap哈希表的线程安全版效率高用于替代HashTable Vector线程安全版Arraylist Stack线程安全版栈 BlockingQueue及其子类线程安全版队列 16. 为何HashMap线程不安全 在JDK1.7中HashMap采用头插法插入元素因此并发情况下会导致环形链表产生死循环。 虽然JDK1.8采用了尾插法解决了这个问题但是并发下的put操作也会使前一个key被后一个key覆盖。由于HashMap有扩容机制 存在也存在A线程进行扩容后B线程执行get方法出现失误的情况。 17. 为何集合类没有实现Cloneable和Serializable接口 克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。 因此应该由集合类的具体实现来决定如何被克隆或者是序列化。 21. 简述JAVA的迭代器(Iterator) Iterator接口提供了很多对集合元素进行迭代的方法。每一个集合类都包含了可以返回迭代器实例的迭代方法。 迭代器可以在迭代的过程中删除底层集合的元素但是不可以直接调用集合的remove(Object Obj)删除可以通过迭代器的remove()方法删除。 22. 简述fail-fast和fail-safe迭代器的区别 ① fail-fast 直接在容器上进行在遍历过程中一旦发现容器中的数据被修改 就会立刻抛出ConcurrentModificationException异常从而导致遍历失败。 常见的使用fail-fast方式的容器有 HashMap 和 ArrayList 等。 ② fail-safe 这种遍历基于容器的一个克隆。因此对容器中的内容修改不影响遍历。 常见的使用fail-safe方式遍历的容器有 ConcurrentHashMap 和 CopyOnWriteArrayList。 25. 简述Java优先级队列(Priority Queue) PriorityQueue是一个基于优先级堆的无界队列它的元素是按照自然顺序(natural order)排序的。 在创建的时候我们可以给它提供一个负责给元素排序的比较器。 PriorityQueue不允许null值因为他们没有自然顺序或者说他们没有任何的相关联的比较器。 最后PriorityQueue不是线程安全的入队和出队的时间复杂度是O(log(n))。 chapter06 IO
01. 简述Java中的IO流 1、按流划分输入流和输出流 2、按操作单位划分字节流和字符流 字节流inputStream、outStream 字符流reader、writer 3、按流的角色划分节点流和处理流 Java l0流的40多个类都是从如下4个抽象类基类中派生出来的 InputStream/Reader所有的输入流的基类前者是字节输入流后者是字符输入流。outputStream/writer所有输出流的基类前者是字节输出流后者是字符输出流。 11. 简述序列化 序列化是一种将对象转换成字节序列的过程用于解决在对对象流进行读写操作时所引发的问题。 序列化可以将对象的状态写在流里进行网络传输或者保存到文件、数据库等系统里并在需要的时候把该流读取出来重新构造 成一个相同的对象。 序列化是通过实现Serializable接口该接口没有需要实现的方法implement Serialiable只是为了标注该对象是可被序列化的 使用一个输出流FileOutStream来构造一个ObjectOutputStream对象接着使用ObjectOutputStream对象的writeObject方法 就可以将参数的obj对象输出到磁盘需要恢复的实话使用输入流。 序列化是将对象转换为容易传输的格式的过程最主要的目的就是传递和保存对象保存对象的完整性和可传递性 12. 简述Java序列化与反序列化的实现 序列化将java对象转化为字节序列由此可以通过网络对象进行传输。 反序列化将字节序列转化为java对象。 具体实现实现 Serializable接口或实现 Externalizable接口 中的 writeExternal() 与 readExternal() 方法。 chapter07 线程基础
01. 简述线程、程序、进程的基本概念以及之间关系 线程与进程相似但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。 与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源所以系统在产生一个线程或是在各个线程之间作切换工作时负担要比进程小得多也正因为如此线程也被称为轻量级进程。 程序是含有指令和数据的文件被存储在磁盘或其他的数据存储设备中也就是说程序是静态的代码。 进程是程序的一次执行过程是系统运行程序的基本单位因此进程是动态的。 系统运行一个程序即是一个进程从创建运行到消亡的过程。 简单来说一个进程就是一个执行中的程序它在计算机中一个指令接着一个指令地执行着同时每个进程还占有某些系统资源如CPU时间、内存空间、文件、输入输出设备的使用权等等。、 换句话说当程序在执行时将会被操作系统载入内存中。线程是进程划分成的更小的运行单位。 线程和进程最大的不同在于基本上各进程是独立的而各线程则不一定因为同一进程中的线程极有可能会相互影响。 从另一角度来说进程属于操作系统的范畴主要是同一段时间内可以同时执行一个以上的程序而线程则是在同一程序内几乎同时执行一个以上的程序段。 02. 简述进程和线程的区别 进程是执行着的应用程序而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。 线程与进程的区别归纳 ① 地址空间和其它资源 进程间相互独立同一进程的各线程间共享。某进程内的线程在其它进程不可见。② 通信 进程间通信IPC线程间可以直接读写进程数据段如全局变量来进行通信需要进程同步和互斥手段的辅助以保证数据的一致性。③ 调度和切换 线程上下文切换比进程上下文切换要快得多。④ 在多线程OS中进程不是一个可执行的实体。 03. 简述线程的基本状态 新建(new) 新创建了一个线程对象。 可运行(runnable) 线程对象创建后其他线程 (比如main线程) 调用了该对象的 start() 方法。 该状态的线程位于可运行线程中等待被线程调度选中获取cpu的使用权。 运行(running) 可运行状态(runnable)的线程获得了cpu时间片 (timeslice)执行程序代码。 阻塞(block) 阻塞状态是指线程因为某种原因放弃了cpu使用权也即让出了cpu timeslice暂时停止运行。 直到线程进入可运行( runnable)状态才有机会再次获得cpu timeslice转到运行(running )状态。 阻塞的情况分三种 ① 等待阻塞运行( running )的线程执行 o.wait()方法JVM会把该线程放入等待队列(waitting queue)中。 ② 同步阻塞运行( running )的线程在获取对象的同步锁时若该同步锁被别的线程占用则JVM会把该线程放入锁池(lockpool)中。 ③ 其他阻塞运行(running)的线程执行Thread.sleep(long ms)或t.join()方法或者发出了I/O请求时JVM会把该线程置为阻塞状态。当sleep()状态超时join()等待线程终止或者超时、或者/O处理完毕时线程重新转入可运行(runnable)状态。 死亡(dead) 线程run()、main()方法执行结束,或者因异常退出了run()方法则该线程结束生命周期。死亡的线程不可再次复生。 chapter08 反射
01. 简述Java反射机制 反射机制使得Java具有 动态获取程序信息和动态调用对象方法 的能力。可以通过以下类调用反射API Class类获得类属性方法 Field类获得类的成员变量 Method类获取类的方法信息 Construct类获取类的构造方法等信息 在程序的运行过程中 构造任意一个类的对象、获取任意一个类的成员变量和成员方法、获取任意一个对象所属的类信息、调用任意一个对象的属性和方法。 02. 简述Class对象 Java中对象可以分为 实例对象 和 Class对象每一个类都有一个Class对象其包含了与该类有关的信息。 获取Class对象的方法 类名.class实例对象.getClass()Class.forName(“类的全限定名”)基本类型的包装类可以调用包装类的Type属性来获得包装类的Class对象 03. 简述Java实例化对象的方式
// 1 new// 2 clone()// 3 反射机制
// 用 Class.forName方法获取类在调用类的newinstance()方法Class? cls Class.forName(com.dao.User);User u (User) cls.newInstance();// 4 序列化、反序列化
// 将一个对象实例化后进行序列化再反序列化也可以获得一个对象(远程通信的场景下使用)ObjectOutputStream out new ObjectOutputStream (new FileOutputStream(D:/data.txt));// 序列化对象out.writeObject(user1); out.close();// 反序列化对象ObjectInputStream in new ObjectInputStream(new FileInputStream(D:/data.txt));User user2 (User) in.readObject();System.out.println(反序列化user user2);in.close();04. 简述Java反射机制优缺点 优点 能够运行时动态获取类的实例提高灵活性与动态编译结合 缺点 使用反射性能较低需要解析字节码将内存中的对象进行解析。解决方案 ① 通过 setAccessible(true) 关闭JDK的安全检查来提升反射速度② 多次创建一个类的实例时有缓存会快很多③ ReflectASM工具类通过字节码生成的方式加快反射速度 相对不安全破坏了封装性因为通过反射可以获得私有方法和属性) chapter09 注解
01. 简述注解 Java 注解用于为 Java 代码提供 元数据 作为元数据注解不直接影响你的代码执行但也有一些类型的注解实际上可以用于这一目的 其可以用于提供信息给编译器在编译阶段时给软件提供信息进行相关的处理在运行时处理写相应代码做对应操作 02. 简述元注解 元注解可以理解为 注解的注解即在注解中使用实现想要的功能。其具体分为 Retention表示注解存在阶段是保留在源码还是在字节码类加载或者运行期JVM中运行 Target表示注解作用的范围 Documented将注解中的元素包含到 Javadoc 中去 Inherited一个被Inherited注解了的注解修饰了一个父类如果他的子类没有被其他注解修饰则它的子类也继承了父类的注解 Repeatable被这个元注解修饰的注解可以同时作用一个对象多次但是每次作用注解又可以代表不同的含义