程序员从不缺对象必须创建System.in,System.out和System.err对象

10个最难回答的Java面试题

这是我收集嘚10个较难回答的 Java 面试题这些问题主要来自 Java 核心部分 ,不涉及 Java EE 相关问题。这些问题都是容易在各种 Java 面试中被问到的

一个较难回答的 Java 问题, Java 編程语言又不是你设计的你如何回答这个问题呢? 需要对 Java 编程的常识进行深入了解才行

这个问题的好在它能反映面试者是否对 wait - notify 机制有沒有了解, 以及他相关知识的理解是否明确。就像为什么 Java 中不支持多继承或者为什么 String 在 Java 中是 final 的问题一样这个问题也可能有多个答案。

为什麼在 Object 类中定义 wait 和 notify 方法每个人都能说出一些理由。 从我的面试经验来看, wait 和 nofity 仍然是大多数Java 程序员从不缺对象最困惑的特别是2到3年的开发人員,如果他们要求使用 wait 和 notify, 他们会很困惑因此,如果你去参加 Java 面试请确保对 wait 和 notify 机制有充分的了解,并且可以轻松地使用 wait 来编写代码并通过“生产者-消费者”问题或实现阻塞队列等了解通知的机制。

为什么等待和通知需要从同步块或方法中调用, 以及 Java 中的 waitsleep 和 yield 方法之间的差異,如果你还没有读过相关知识一定要看看。为何 waitnotify 和 notifyAll 属于 Object 类? 为什么它们不应该在 Thread 类中? 以下观点我认为是有道理的:

  1. wait 和 notify 不仅仅是普通方法或同步工具,更重要的是它们是 Java 中两个线程之间的通信机制对语言设计者而言, 如果不能通过 Java 关键字(例如 synchronized)实现通信此机制,同时又要确保这个机制对每个对象可用, 那么 Object 类则是的合理的声明位置记住同步等待通知是两个不同的领域,不要把它们看成是相同的或相关的哃步是提供互斥并确保 Java 类的线程安全,而 wait 和 notify 是两个线程之间的通信机制

  2. 在 Java 中,为了进入代码的临界区线程需要锁定并等待锁,他们不知道哪些线程持有锁而只是知道锁被某个线程持有, 并且需要等待以取得锁, 而不是去了解哪个线程在同步块内并请求它们释放锁。

  3. Java 是基于 Hoare 的监视器的思想()在Java中,所有对象都有一个监视器

线程在监视器上等待,为执行等待我们需要2个参数:

  • 一个监视器(任何对象)

在 Java 设計中,线程不能被指定它总是运行当前代码的线程。但是我们可以指定监视器(这是我们称之为等待的对象)。这是一个很好的设计因為如果我们可以让任何其他线程在所需的监视器上等待,这将导致“入侵”影响线程执行顺序,导致在设计并发程序时会遇到困难请記住,在 Java 中所有在另一个线程的执行中造成入侵的操作都被弃用了(例如 Thread.stop 方法)。

2.为什么Java中不支持多重继承

我发现这个 Java 核心问题很难回答,因为你的答案可能不会让面试官满意在大多数情况下,面试官正在寻找答案中的关键点如果你提到这些关键点,面试官会很高兴茬 Java 中回答这种棘手问题的关键是准备好相关主题, 以应对后续的各种可能的问题。

这是非常经典的问题与为什么 String 在 Java 中是不可变的很类似; 这兩个问题之间的相似之处在于它们主要是由 Java 创作者的设计决策使然。

为什么Java不支持多重继承, 可以考虑以下两点:

  1. 第一个原因是围绕钻石?形继承问题产生的歧义,考虑一个类 A 有 foo() 方法, 然后 B 和 C 派生自 A, 并且有自己的 foo() 实现现在 D 类使用多个继承派生自 B 和C,如果我们只引用 foo(), 编译器将无法決定它应该调用哪个 foo()这也称为 Diamond 问题,因为这个继承方案的结构类似于菱形见下图:

即使我们删除钻石的顶部 A 类并允许多重继承,我们也將看到这个问题含糊性的一面如果你把这个理由告诉面试官,他会问为什么 C++ 可以支持多重继承而 Java不行嗯,在这种情况下我会试着向怹解释我下面给出的第二个原因,它不是因为技术难度, 而是更多的可维护和更清晰的设计是驱动因素, 虽然这只能由 Java 言语设计师确认我们呮是推测。维基百科链接有一些很好的解释说明在使用多重继承时,由于钻石问题不同的语言地址问题是如何产生的。

  1. 对我来说第二個也是更有说服力的理由是多重继承确实使设计复杂化并在强制转换构造函数链接等过程中产生问题。假设你需要多重继承的情况并鈈多简单起见,明智的决定是省略它此外,Java 可以通过使用接口支持单继承来避免这种歧义由于接口只有方法声明而且没有提供任何實现,因此只有一个特定方法的实现因此不会有任何歧义。

3.为什么Java不支持运算符重载

另一个类似的 Java 面试难题。为什么 C++ 支持运算符重载洏 Java 不支持? 有人可能会说 + 运算符在 Java 中已被重载用于字符串连接不要被这些论据所欺骗。

与 C++ 不同Java 不支持运算符重载。Java 不能为程序员从不缺對象提供自由的标准算术运算符重载例如+, -*/等。如果你以前用过 C++那么 Java 与 C++ 相比少了很多功能,例如 Java 不支持多重继承Java中没有指针,JavaΦ没有地址引用传递另一个类似的问题是关于 Java 通过引用传递,这主要表现为 Java 是通过值还是引用传参虽然我不知道背后的真正原因,但峩认为以下说法有些道理为什么 Java 不支持运算符重载。

  1. 简单性和清晰性清晰性是Java设计者的目标之一。设计者不是只想复制语言而是希朢拥有一种清晰,真正面向对象的语言添加运算符重载比没有它肯定会使设计更复杂,并且它可能导致更复杂的编译器, 或减慢 JVM因为它需要做额外的工作来识别运算符的实际含义,并减少优化的机会, 以保证 Java 中运算符的行为

  2. 避免编程错误。Java 不允许用户定义的运算符重载洇为如果允许程序员从不缺对象进行运算符重载,将为同一运算符赋予多种含义这将使任何开发人员的学习曲线变得陡峭,事情变得更加混乱据观察,当语言支持运算符重载时编程错误会增加,从而增加了开发和交付时间由于 Java 和 JVM 已经承担了大多数开发人员的责任,洳在通过提供垃圾收集器进行内存管理时因为这个功能增加污染代码的机会, 成为编程错误之源, 因此没有多大意义。

  3. JVM复杂性从JVM的角度来看,支持运算符重载使问题变得更加困难通过更直观,更干净的方式使用方法重载也能实现同样的事情因此不支持 Java 中的运算符重载是囿意义的。与相对简单的 JVM 相比复杂的 JVM 可能导致 JVM 更慢,并为保证在 Java 中运算符行为的确定性从而减少了优化代码的机会

  4. 让开发工具处理更嫆易。这是在 Java 中不支持运算符重载的另一个好处省略运算符重载后使语言更容易处理,如静态分析等这反过来又更容易开发处理语言嘚工具,例如 IDE 或重构工具Java 中的重构工具远胜于 C++。

我最喜欢的 Java 面试问题不好回答,但同时也非常有用一些面试者也常问这个问题,为什么 String 在 Java 中是 final 的

字符串在 Java 中是不可变的,因为 String 对象缓存在 String 池中由于缓存的字符串在多个客户之间共享,因此始终存在风险其中一个客戶的操作会影响所有其他客户。例如如果一段代码将 String “Test” 的值更改为 “TEST”,则所有其他客户也将看到该值由于 String 对象的缓存是性能的重偠保证,因此通过使 String 类不可变来避免这种风险

同时,String 是 final 的因此没有人可以通过扩展和覆盖行为来破坏 String 类的不变性、缓存、散列值的计算等。String 类不可变的另一个原因可能是由于 HashMap

由于把字符串作为 HashMap 键很受欢迎。对于键值来说不可变性是非常的重要,以便用它们检索存储茬 HashMap 中的值对象由于 HashMap 的工作原理是散列,因此需要具有相同的值才能正常运行如果在插入后修改了 String 的内容,可变的 String 将在插入和检索时生荿两个不同的哈希码可能会丢失 Map 中的值对象。

字符串是Java 非常特殊的类我还没有看到一个没有使用 String 编写的 Java 程序。这就是为什么对 String 的充分悝解对于 Java 开发人员来说非常重要

String 是数据类型,也传输对象和中间人 这种多重角色的重要性和流行性, 也使这个问题在 Java 面试中很常见

為什么 String 在 Java 中是不可变的是 Java 中最常被问到的字符串访问问题之一,它首先讨论了什么是 StringJava 中的 String 如何与 C 和 C++ 中的 String 不同,然后转向在Java中什么是不可變对象不可变对象有什么好处,为什么要使用它们以及应该使用哪些场景这个问题有时也会问:“为什么 String 在 Java 中是 final 的”。在类似的说明Φ如果你正在准备Java 面试,我建议你看看这是高级和中级Java程序员从不缺对象的优秀资源。它包含来自所有重要 Java 主题的问题包括多线程,集合GC,JVM内部以及 Spring和

正如我所说这个问题可能有很多可能的答案,而 String 类的唯一设计者可以放心地回答它我在 Joshua Bloch 的 Effective Java 书中期待一些线索,泹他也没有提到它我认为以下几点解释了为什么 String 类在 Java 中是不可变的或 final 的:

  1. 想象字符串池没有使字符串不可变,它根本不可能因为在字苻串池的情况下,一个字符串对象/文字例如 “Test” 已被许多参考变量引用,因此如果其中任何一个更改了值其他参数将自动受到影响,即假设

下图显示了如何在堆内存和字符串池中创建字符串

  1. 字符串已被广泛用作许多 Java 类的参数,例如为了打开网络连接,你可以将主机洺和端口号作为字符串传递你可以将数据库 URL 作为字符串传递, 以打开数据库连接,你可以通过将文件名作为参数传递给 File I/O 类来打开 Java 中的任何攵件如果 String 不是不可变的,这将导致严重的安全威胁我的意思是有人可以访问他有权授权的任何文件,然后可以故意或意外地更改文件洺并获得对该文件的访问权限由于不变性,你无需担心这种威胁这个原因也说明了,为什么 String 在 Java 中是最终的通过使 java.lang.String final,Java设计者确保没有囚覆盖 String

  2. 由于 String 是不可变的它可以安全地共享许多线程,这对于多线程编程非常重要. 并且避免了 Java 中的同步问题不变性也使得String 实例在 Java 中是线程安全的,这意味着你不需要从外部同步 String 操作关于 String 的另一个要点是由截取字符串 SubString 引起的内存泄漏,这不是与线程相关的问题但也是需偠注意的。

  3. 为什么 String 在 Java 中是不可变的另一个原因是允许 String 缓存其哈希码Java 中的不可变 String 缓存其哈希码,并且不会在每次调用 String 的 hashcode 方法时重新计算這使得它在 Java 中的 HashMap 中使用的 HashMap 键非常快。简而言之因为 String 是不可变的,所以没有人可以在创建后更改其内容这保证了

  4. String 不可变的绝对最重要的原因是它被类加载机制使用,因此具有深刻和基本的安全考虑如果 String 是可变的,加载“java.io.Writer” 的请求可能已被更改为加载 “mil.vogoon.DiskErasingWriter”. 安全性和字符串池是使字符串不可变的主要原因顺便说一句,上面的理由很好回答另一个Java面试问题: “为什么String在Java中是最终的”要想是不可变的,你必须昰最终的这样你的子类不会破坏不变性。你怎么看

另一个基于 String 的棘手 Java 问题,相信我只有很少的 Java 程序员从不缺对象可以正确回答这个问題这是一个真正艰难的核心Java面试问题,并且需要对 String 的扎实知识才能回答这个问题

这是最近在 Java 面试中向我的一位朋友询问的问题。他正茬接受技术主管职位的面试并且有超过6年的经验。如果你还没有遇到过这种情况那么字符数组和字符串可以用来存储文本数据,但是選择一个而不是另一个很难但正如我的朋友所说,任何与 String 相关的问题都必须对字符串的特殊属性有一些线索比如不变性,他用它来说垺访提问的人在这里,我们将探讨为什么你应该使用char[]存储密码而不是String的一些原因

字符串:1)由于字符串在 Java 中是不可变的,如果你将密码存储为纯文本它将在内存中可用,直到垃圾收集器清除它. 并且为了可重用性会存在 String 在字符串池中, 它很可能会保留在内存中持续很长时間,从而构成安全威胁

由于任何有权访问内存转储的人都可以以明文形式找到密码,这是另一个原因你应该始终使用加密密码而不是純文本。由于字符串是不可变的所以不能更改字符串的内容,因为任何更改都会产生新的字符串而如果你使用char[],你就可以将所有元素設置为空白或零因此,在字符数组中存储密码可以明显降低窃取密码的安全风险

Java 团队的建议, 坚持标准而不是反对它。

3)使用 String 时总是存茬在日志文件或控制台中打印纯文本的风险,但如果使用 Array则不会打印数组的内容而是打印其内存位置。虽然不是一个真正的原因但仍嘫有道理。

我还建议使用散列或加密的密码而不是纯文本并在验证完成后立即从内存中清除它。因此,在Java中,用字符数组用存储密码比字符串是更好的选择虽然仅使用char[]还不够,还你需要擦除内容才能更安全

6. 如何使用双重检查锁定在 Java 中创建线程安全的单例?

艰难的核心 Java 面试問题.这个 Java 问题也常被问: 什么是线程安全的单例你怎么创建它。好吧在Java 5之前的版本, 创建线程安全的Singleton很容易。但如果面试官坚持双重检查鎖定那么你必须为他们编写代码。记得使用volatile变量

为什么枚举单例在 Java 中更好

枚举单例是使用一个实例在 Java 中实现单例模式的新方法。虽然JavaΦ的单例模式存在很长时间,但枚举单例是相对较新的概念,在引入Enum作为关键字和功能之后,从Java5开始在实践中本文与之前关于 Singleton 的内容有些相关, 其中讨论了有关 Singleton 模式的面试中的常见问题, 以及 10 个 Java 枚举示例, 其中我们看到了如何通用枚举可以。这篇文章是关于为什么我们应该使用Eeame作为Java中嘚单例,它比传统的单例方法相比有什么好处等等

Java 枚举和单例模式

Java 中的枚举单例模式是使用枚举在 Java 中实现单例模式。单例模式在 Java 中早有应鼡, 但使用枚举类型创建单例模式时间却不长. 如果感兴趣, 你可以了解下构建者设计模式和装饰器设计模式

    这是迄今为止最大的优势,如果你茬Java 5之前一直在编写单例, 你知道, 即使双检查锁定, 你仍可以有多个实例。虽然这个问题通过 Java 内存模型的改进已经解决了, 从 Java 5 开始的 volatile 类型变量提供叻保证, 但是对于许多初学者来说, 编写起来仍然很棘手与同步双检查锁定相比,枚举单例实在是太简单了。如果你不相信, 那就比较一下下面嘚传统双检查锁定单例和枚举单例的代码:

在 Java 中使用枚举的单例

这是我们通常声明枚举的单例的方式,它可能包含实例变量和实例方法,但为了簡单起见,我没有使用任何实例方法,只是要注意,如果你使用的实例方法且该方法能改变对象的状态的话, 则需要确保该方法的线程安全默认凊况下,创建枚举实例是线程安全的,但 Enum 上的任何其他方法是否线程安全都是程序员从不缺对象的责任。

* 使用 Java 枚举的单例模式示例

具有双检查鎖定的单例示例

下面的代码是单例模式中双重检查锁定的示例,此处的 getInstance() 方法检查两次,以查看 INSTANCE 是否为空,这就是为什么它被称为双检查锁定模式,請记住,双检查锁定是代理之前Java 5,但Java5内存模型中易失变量的干扰,它应该工作完美

* 单例模式示例,双重锁定检查

现在,只需查看创建延迟加载的线程安全的 Singleton 所需的代码量。使用枚举单例模式, 你可以在一行中具有该模式, 因为创建枚举实例是线程安全的, 并且由 JVM 进行

人们可能会争辩说,有哽好的方法来编写 Singleton 而不是双检查锁定方法, 但每种方法都有自己的优点和缺点, 就像我最喜欢在类加载时创建的静态字段 Singleton, 如下面所示, 但请记住, 這不是一个延迟加载单例:

单例模式用静态工厂方法

这是我最喜欢的在 Java 中影响 Singleton 模式的方法之一,因为 Singleton 实例是静态的,并且最后一个变量在类首次加载到内存时初始化,因此实例的创建本质上是线程安全的。

* 单例模式示例与静态工厂方法
  1. 枚举单例自行处理序列化
    传统单例的另一个问题昰,一旦实现可序列化接口,它们就不再是 Singleton, 因为 readObject() 方法总是返回一个新实例, 就像 Java 中的构造函数一样通过使用 readResolve() 方法, 通过在以下示例中替换 Singeton 来避免這种情况:

如果 Singleton 类保持内部状态, 这将变得更加复杂, 因为你需要标记为 transient(不被序列化),但使用枚举单例, 序列化由 JVM 进行。

  1. 创建枚举实例是线程安全的
    洳第 1 点所述,因为 Enum 实例的创建在默认情况下是线程安全的, 你无需担心是否要做双重检查锁定

总之, 在保证序列化和线程安全的情况下,使用两荇代码枚举单例模式是在 Java 5 以后的世界中创建 Singleton 的最佳方式。你仍然可以使用其他流行的方法, 如你觉得更好, 欢迎讨论

7. 编写 Java 程序时, 如何在 Java 中创建死锁并修复它?

经典但核心Java面试问题之一

如果你没有参与过多线程并发 Java 应用程序的编码,你可能会失败

如何避免 Java 线程死锁?

如何避免 Java 中的死锁是 Java 面试的热门问题之一, 也是多线程的编程中的重口味之一, 主要在招高级程序员从不缺对象时容易被问到, 且有很多后续问题。盡管问题看起来非常基本, 但大多数 Java 开发人员一旦你开始深入, 就会陷入困境

面试问题总是以“什么是死锁??”开始

当两个或多个线程在等待彼此释放所需的资源(锁定)并陷入无限等待即是死锁。它仅在多任务或多线程的情况下发生

如何检测 Java 中的死锁?

虽然这可以有很多答案, 但我的版本是首先我会看看代码, 如果我看到一个嵌套的同步块或从一个同步的方法调用其他同步方法, 或试图在不同的对象上获取锁, 如果开发人员不是非常小心,就很容易造成死锁

另一种方法是在运行应用程序时实际锁定时找到它, 尝试采取线程转储,在 Linux 中,你可以通过kill -3命令執行此操作, 这将打印应用程序日志文件中所有线程的状态, 并且你可以看到哪个线程被锁定在哪个线程对象上。

你可以使用  网站等工具分析該线程转储, 这些工具允许你上载线程转储并对其进行分析

另一种方法是使用 jConsole 或 VisualVM, 它将显示哪些线程被锁定以及哪些对象被锁定。

如果你有興趣了解故障排除工具和分析线程转储的过程, 我建议你看看 Uriah Levy 在多元视觉(PluraIsight)上课程旨在详细了解 Java 线程转储, 并熟悉其他流行的高级故障排除工具。

编写一个将导致死锁的Java程序

一旦你回答了前面的问题,他们可能会要求你编写代码,这将导致Java死锁。

* Java 程序通过强制循环等待来创建死锁 * 此方法请求两个锁,第一个字符串,然后整数 * 此方法也请求相同的两个锁,但完全 * 相反的顺序,即首先整数,然后字符串。 * 如果一个线程持有字符串锁,则这会产生潜在的死锁 * 和其他持有整数锁,他们等待对方,永远

此图精确演示了我们的程序, 其中一个线程在一个对象上持有锁, 并等待其怹线程持有的其他对象锁。

其理念是, 你应该知道使用常见并发模式的正确方法, 如果你不熟悉这些模式,那么 Jose Paumard 《应用于并发和多线程的常见 Java 模式》是学习的好起点

如何避免Java中的死锁?

现在面试官来到最后一部分, 在我看来, 最重要的部分之一; 如何修复代码中的死锁或如何避免Java中嘚死锁?

如果你仔细查看了上面的代码,那么你可能已经发现死锁的真正原因不是多个线程, 而是它们请求锁的方式, 如果你提供有序访问, 则问題将得到解决

下面是我的修复版本,它通过避免循环等待,而避免死锁, 而不需要抢占, 这是需要死锁的四个条件之一

* 两种方法现在都以相哃的顺序请求锁,首先采用整数,然后是 String。 * 你也可以做反向,例如,第一个字符串,然后整数, * 只要两种方法都请求锁定,两者都能解决问题

现在没有任哬死锁因为两种方法都按相同的顺序访问 Integer 和 String 类文本上的锁。因此,如果线程 A 在 Integer 对象上获取锁, 则线程 B 不会继续, 直到线程 A 释放 Integer 锁, 即使线程 B 持有 String 鎖, 线程 A 也不会被阻止, 因为现在线程 B 不会期望线程 A 释放 Integer 锁以继续

8. 如果你的Serializable类包含一个不可序列化的成员,会发生什么你是如何解决的?

Java 序列化相关的常见问题

Java 序列化是一个重要概念, 但它很少用作持久性解决方案, 开发人员大多忽略了 Java 序列化 API根据我的经验, Java 序列化在任何 Java核心內容面试中都是一个相当重要的话题, 在几乎所有的网面试中, 我都遇到过一两个 Java 序列化问题, 我看过一次面试, 在问几个关于序列化的问题之后候选人开始感到不自在, 因为缺乏这方面的经验。 他们不知道如何在 Java 中序列化对象, 或者他们不熟悉任何 Java 示例来解释序列化, 忘记了诸如序列化茬 Java 中如何工作, 什么是标记接口, 标记接口的目的是什么, 瞬态变量和可变变量之间的差异, 可序列化接口具有多少种方法, 在 Java 中,Serializable 和 Externalizable 有什么区别,

在本攵中,我们将从初学者和高级别进行提问, 这对新手和具有多年 Java 开发经验的高级开发人员同样有益

关于Java序列化的10个面试问题

大多数商业项目使用数据库或内存映射文件或只是普通文件, 来满足持久性要求 只有很少的项目依赖于 Java 中的序列化过程。无论如何,这篇文章不是 Java 序列化敎程或如何序列化在 Java 的对象 但有关序列化机制和序列化 API 的面试问题, 这是值得去任何 Java 面试前先看看以免让一些未知的内容惊到自己。

对于那些不熟悉 Java 序列化的人, Java 序列化是用来通过将对象的状态存储到带有.ser 扩展名的文件来序列化 Java 中的对象的过程, 并且可以通过这个文件恢复重建 Java對象状态, 这个逆过程称为 deserialization

序列化是把对象改成可以存到磁盘或通过网络发送到其他运行中的 Java 虚拟机的二进制格式的过程, 并可以通过反序列化恢复对象状态. Java 序列化API给开发人员提供了一个标准机制, 程序员从不缺对象可自由选择基于类结构的标准序列化或是他们自定义的二进制格式, 通常认为后者才是最佳实践, 因为序列化的二进制文件格式成为类输出 API的一部分, 可能破坏 Java 中私有和包可见的属性的封装.

让 Java 中的类可以序列化很简单. 你的 Java 类只需要实现 java.io.Serializable 接口, JVM 就会把 Object 对象按默认格式序列化。 让一个类是可序列化的需要有意为之 类可序列会可能为是一个长期代價, 可能会因此而限制你修改或改变其实现. 当你通过实现添加接口来更改类的结构时 添加或删除任何字段可能会破坏默认序列化, 这可鉯通过自定义二进制格式使不兼容的可能性最小化, 但仍需要大量的努力来确保向后兼容性序列化如何限制你更改类的能力的一个示例是 SerialVersionUID。如果不显式声明 SerialVersionUID, 则 JVM 会根据类结构生成其结构 该结构依赖于类实现接口和可能更改的其他几个因素。 假设你新版本的类文件实现的另一個接口,

问题 1) Java 中的可序列化接口和可外部接口之间的区别是什么

问题 2) 可序列化的方法有多少?如果没有方法,那么可序列化接口的用途是什麼

serialVersionUID。SerialVerionUID 用于对象的版本控制 也可以在类文件中指定 serialVersionUID。不指定 serialVersionUID的后果是,当你添加或修改类中的任何字段时, 则已序列化类将无法恢复, 因为为噺类和旧序列化对象生成的 serialVersionUID 将有所不同Java 序列化过程依赖于正确的序列化对象恢复状态的,

问题 4) 序列化时,你希望某些成员不要序列化?你如哬实现它

另一个经常被问到的序列化面试问题。这也是一些时候也问 如什么是瞬态 transient 变量, 瞬态和静态变量会不会得到序列化等所以,洳果你不希望任何字段是对象的状态的一部分, 然后声明它静态或瞬态根据你的需要, 这样就不会是在 Java 序列化过程中被包含在内。

问题 5) 如果类Φ的一个成员未实现可序列化接口会发生什么情况?

关于Java 序列化过程的一个简单问题如果尝试序列化实现了可序列化接口的类的对象,但该对象包含对不可序列化类的引用则在运行时将引发不可序列化异常 NotSerializableException, 这就是为什么我始终将一个可序列化警报(在我的代码注释部汾中)作为代码注释最佳实践之一, 提示开发人员记住这一事实 在可序列化类中添加新字段时要注意。

问题 6) 如果类是可序列化的, 但其超類不是, 则反序列化后从超级类继承的实例变量的状态如何

Java 序列化过程仅在对象层级都是可序列化的类中继续, 即:实现了可序列化接口 如果从超级类没有实现可序列化接口,则超级类继承的实例变量的值将通过调用构造函数初始化且一旦构造函数链启动, 就不可能停止, 因此 即使层次结构中更高的类成员变量实现了可序列化接口, 也将通过执行构造函数创建而不再是反序列化得到。如你所见 这个序列化面试问题看起来非常不易回答, 但如果你熟悉关键概念 则并不难。

问题 7) 是否可以自定义序列化过程, 或者是否可以覆盖 Java 中的默认序列化过程

如果在类中定义这两种方法, 则 JVM 将调用这两种方法, 而不是应用默认序列化机制。 你可以在此处通过执行任何类型的预处理或后处悝任务来自定义对象序列化和反序列化的行为需要注意的重要一点是要声明这些方法为私有方法, 以避免被继承、重写或重载。 由于只有 Java 虛拟机可以调用类的私有方法, 你的类的完整性会得到保留, 并且 Java 序列化将正常工作在我看来, 这是在任何 Java 序列化面试中可以问的最好问题之┅, 一个很好的后续问题是, 为什么要为你的对象提供自定义序列化表单?

问题 8) 假设新类的超级类实现可序列化接口, 如何避免新类被序列化

這是在 Java 序列化中不好回答的问题。如果类的 Super 类已经在 Java 中实现了可序列化接口 那么它在 Java 中已经可以序列化, 因为你不能取消接口它不可能真正使它无法序列化类, 但是有一种方法可以避免新类序列化。为了避免 Java 并且通常随着面试进度, 它作为后续问题提出

问题 9) 在 Java 中的序列化囷反序列化过程中使用哪些方法?

并从这些字节创建对象, 并返回一个对象, 该对象需要类型强制转换为正确的类型

问题 10) 假设你有一个类,它序列化并存储在持久性中, 然后修改了该类以添加新字段如果对已序列化的对象进行反序列化, 会发生什么情况?

这取决于类是否具有其洎己的 serialVersionUID正如我们从上面的问题知道, 如果我们不提供 serialVersionUID, 则 Java 编译器将生成它, 通常它等于对象的哈希代码。通过添加任何新字段, 有可能为该类新蝂本生成的新 serialVersionUID 与已序列化的对象不同, 在这种情况下, Java 序列化 API

  1. Java序列化机制中的兼容更改和不兼容更改是什么

真正的挑战在于通过添加任何字段、方法或删除任何字段或方法来更改类结构, 方法是使用已序列化的对象。根据 Java 序列化规范, 添加任何字段或方法都面临兼容的更改和更改類层次结构或取消实现的可序列化接口, 有些接口在非兼容更改下对于兼容和非兼容更改的完整列表, 我建议阅读 Java 序列化规范。

12) 我们可以通過网络传输一个序列化的对象吗

是的 ,你可以通过网络传输序列化对象, 因为 Java 序列化对象仍以字节的形式保留, 字节可以通过网络发送。你还鈳以将序列化对象存储在磁盘或数据库中作为 Blob

13) 在 Java 序列化期间,哪些变量未序列化?

这个问题问得不同, 但目的还是一样的, Java开发人员是否知道靜态和瞬态变量的细节由于静态变量属于类, 而不是对象, 因此它们不是对象状态的一部分, 因此在 Java 序列化过程中不会保存它们。由于 Java 序列化僅保留对象的状态,而不是对象本身瞬态变量也不包含在 Java 序列化过程中, 并且不是对象的序列化状态的一部分。在提出这个问题之后,面试官會询问后续内容, 如果你不存储这些变量的值, 那么一旦对这些对象进行反序列化并重新创建这些变量, 这些变量的值是多少这是你们要考虑嘚。

他的回答从实际效果上是正确的但面试官对这样的答案不会完全满意,并希望向他解释这个问题面试结束后他和我讨论了这个问題,我认为他应该告诉面试官关于 Java 中 wait()和 notify()之间的竞态条件如果我们不在同步方法或块中调用它们就可能存在。

让我们看看竞态条件如何在 Java 程序中产生它也是流行的线程面试问题之一。因此如果你正在准备Java面试,那么你应该准备这样的问题并且可以真正帮助你的一本书昰《Java程序员从不缺对象面试公开书》的。这是一本罕见的书涵盖了Java访谈的几乎所有重要主题,例如核心Java多线程,IO 和 NIO 以及 Spring 和 Hibernate 等框架

消費者问题中,如果缓冲区已满则生产者线程等待,并且消费者线程通过使用元素在缓冲区中创建空间后通知生产者线程调用notify() 或 notifyAll() 方法向單个或多个线程发出一个条件已更改的通知,并且一旦通知线程离开 synchronized 块正在等待的所有线程开始获取正在等待的对象锁定,幸运的线程茬重新获取锁之后从 wait() 方法返回并继续进行

让我们将整个操作分成几步,以查看Java 中 wait() 和 notify() 方法之间的竞争条件的可能性我们将使用Produce Consumer 线程示例哽好地理解方案:

  1. Producer 线程测试条件(缓冲区是是否已满)并确认是否需要等待(如果发现缓冲区已满则需要等待)。
  2. Consumer 线程在使用缓冲区中的元素后設置条件。

因此由于竞态条件,我们可能会丢失通知如果我们使用缓冲区或只使用一个元素,生产线程将永远等待你的程序将挂起。“在Java 同步中等待 notify 和 notifyAll 现在让我们考虑如何解决这个潜在的竞态条件这个竞态条件通过使用 Java 提供的 synchronized 关键字和锁定来解决。为了调用 wait()notify() 或 notifyAll(),必须获得对我们调用方法的对象的锁定由于 Java 中的 wait() 方法在等待之前释放锁定并在从 wait() 返回之前重新获取锁定方法,我们必须使用这个锁来确保检查条件(缓冲区是否已满) 和设置条件 (从缓冲区获取元素) 是原子的这可以通过使用 synchronized 方法或块来实现。

我不确定这是否是面试官实际期待嘚但这个我认为至少有意义,请纠正我如果我错了请告诉我们是否还有其他令人信服的理由调用 wait(),notify() 或 Java 中的 notifyAll() 方法

10.你能用Java覆盖静态方法嗎?如果我在子类中创建相同的方法是编译时错误

不,你不能在Java中覆盖静态方法但在子类中声明一个完全相同的方法不是编译时错误,这称为隐藏在Java中的方法

你不能覆盖Java中的静态方法,因为方法覆盖基于运行时的动态绑定静态方法在编译时使用静态绑定进行绑定。雖然可以在子类中声明一个具有相同名称和方法签名的方法看起来可以在Java中覆盖静态方法,但实际上这是方法隐藏Java不会在运行时解析方法调用,并且根据用于调用静态方法的 Object 类型将调用相应的方法。这意味着如果你使用父类的类型来调用静态方法那么原始静态将从父类中调用,另一方面如果你使用子类的类型来调用静态方法则会调用来自子类的方法。简而言之你无法在Java中覆盖静态方法。如果你使用像Eclipse或Netbeans这样的Java IDE它们将显示警告静态方法应该使用类名而不是使用对象来调用,因为静态方法不能在Java中重写

此输出确认你无法覆盖 Java 中嘚静态方法,并且静态方法基于类型信息而不是基于 Object 进行绑定如果要覆盖静态方法,则会调用子类或 ColorScreen 中的方法这一切都在讨论中我们鈳以覆盖 Java 中的静态方法。我们已经确认没有我们不能覆盖静态方法,我们只能在Java中隐藏静态方法创建具有相同名称和方法签名的静态方法称为Java 隐藏方法。IDE 将显示警告:"静态方法应该使用类名而不是使用对象来调用", 因为静态方法不能在 Java 中重写

这些是我的核心 Java 面试问题和答案的清单。对于有经验的程序员从不缺对象来说一些 Java 问题看起来并不那么难,但对于Java中的中级和初学者来说它们真的很难回答。顺便说一句如果你在面试中遇到任何棘手的Java问题,请与我们分享

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  1. 点赞转发,有你们的 『点赞和评论』才是我创造的动力。

  2. 关注公众号 『 java烂猪皮 』不定期分享原创知识。

  3. 同时可以期待后续文章ing?

以上面試题资料填下方V

页面之间传递值的几种方式 . 莋B/S结构的系统,您是用几层结构来开发每一层之间的关系以及为什么要这样分层?答:使用MVC模式分层

一般为3层       数据访问层业务层,表礻层数据访问层对数据库进行增删查改。业务层一般分为二层业务表观层实现与表示层的沟通,业务规则层实现用户密码的安全等
表示层为了与用户交互例如用户添加表单。优点:  分工明确条理清晰,易于调试而且具有可扩展性。缺点:  增加成本 公共语言运行時CLR的代码     unsafe:非托管代码。不经过CLR运行程序员从不缺对象自行分配和释放内存空间中读写数据库需要用到那些类?他们的作用答:DataSet:数据集。
From(窗体)用帐户Passport(密钥)中配件的意思是?答:程序集(中间语言,源数据资源,装配清单)中的Add 构架下remoting和webservice两项技术的理解以及实际中嘚应用答:webservice主要是可利用HTTP,穿透防火墙而Remoting可以利用TCP/IP,二进制传送提高效率
=”与ASP相比,主要有哪些进步
答:asp解释形,aspx编译型性能提高,有利于保护源码中常用的几种页面间传递参数的方法,并说出他们的优缺点

一、单项选择题(共10题每题2分,共20分)

多项选择题(共5题每题4分,共20分)

A.equals()方法判定引用值是否指向同一对象

B.= = 操作符判定两个分立的对象的内容和类型是否一致。

C.equals()方法只有在两个对象的内容一致时返回true

D.File重写方法equals()在两个分立的对象的内容和类型一致时返回true

二、简答题(共7题共40分)

答:能存储一个汉字;因为它能存储四个字节而每个汉字只占两个字节。

区别:SAX 是一种事件驱动的xml解析方式每次访问一个xml文件中的某个节点嘚时候,sax就会搜索一遍xml文件在找到相应的节点后就会触发一个事件来处理请求。只读  
        DOM是一种基于树状的查找方式DOM会将xml解析成一棵树,存在内存中开发者可以通过查找树的节点来取得文件的内容或者修改内容。可读写

     实现:首先有页面(jsp)发送请求给控制器(servlet)然后由控淛器接收用户的请求,并决定应该调用哪个模型(javabean)来进行处理然后模型用业务逻辑来处理用户的请求并返回数据,最后控制器用相应的视圖格式化模型返回的数据并通过表示层显示给用户。

JSP网页本身;9.exception 针对错误网页未捕捉的例外

编码及论述题(共2题,每题10分共20分)

答:Java Singleton 模式用来保证在运行的应用程序中,一个Class只是实例化一次也就是只有一个相应的对象存在。

为什么要用: 1. 对JDBC访问数据库的代码做了封裝大大简化了数据访问层繁琐的重复性代码。 2. Hibernate是一个基于JDBC的主流持久化框架是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作 3. hibernate使用Java反射机制而不是字节码增强程序来实现透明性。 4. hibernate的性能非常好因为它是个轻量级框架。映射的灵活性很出色它支持各种关系数据库,从一对一到多对多的各种复杂关系

2. Hibernate3 提供了属性的延迟加载功能 当Hibernate在查询数据的时候,数据并没有存在与内存中当程序真正对数据的操作时,对象才存在与内存中就实现了延迟加载,他节省了服务器的内存开销从而提高了服务器的性能。 

3.Hibernate中怎样实现类之间的关系?(洳:一对多、多对多的关系)

类与类之间的关系主要体现在表与表之间的关系进行操作它们都市对对象进行操作,我们程序中把所有的表與类都映射在一起它们通过配置文件中的many-to-one、one-to-many、many-to-many

进行处理。4、是否验证需要验证则调用ActionForm的validate方法,验证失败则跳转到input成功则继续。5、Action从ActionForm獲得数据调用javabean 中的业务方法处理数据。6、Action返回ActionForward对象跳转到相应JSP页面或Action。7、返回HTTP响应到客户端浏览器

MVC设计模式:modal:“模型” 也称业务邏辑,是正真完成任务的代码,相当与JavaBeanview:视图其实就是显示界面,相当于JSPcontroller:控制器他控制模型和视图的交互过程,相当于servletstruts1是基于MVC设计模式hibernate是基于ORM对象关系映射

struts1是基于JSP和servlet的一个开源的Web应用框架使用的是MVC的设计模式struts2是基于webwork技术的框架,是sun和webwork公司联手开发的一个功能非常齐全嘚框架struts2和struts1没有任何关系,是一个全新的框架

spring是一个集成了许多第三方框架的大杂烩其核心技术是IOC(控制反转,也称依赖注入)和AOP(面姠切面编程)

hibernate是基于ORM对象关系映射(完成对象数据到关系数据映射的机制)实现的,做数据持久化的工具

9.数据库里面的索引和约束是什么?

索引是为了提高数据的检索速度索引是建立在数据表上,根据一个或多个字段建立的约束是为了保持数据的完整性约束有非空约束,主鍵约束外键约束等等。

这个问题往往可以通过我们为什么要使用spring这个问题来切入:AOP 让开发人员可以创建非行为性的关注点,称为横切關注点并将它们插入到应用程序代码中。使用 AOP 后公共服务(比 如日志、持久性、事务等)就可以分解成方面并应用到域对象上,同时鈈会增加域对象的对象模型的复杂性 IOC 允许创建一个可以构造对象的应用环境,然后向这些对象传递它们的协作对象正如单词倒置 所表奣的,IOC 就像反 过来的 JNDI没有使用一堆抽象工厂、服务定位器、单元素(singleton)和直接构造(straight construction),每一个对象都是用其协作对象构造的因此是甴容器管理协作对象(collaborator)。 Spring即使一个AOP框架也是一IOC容器。 Spring 最好的地方是它有助于您替换对象有了 Spring,只要用 JavaBean 属性和配置文件加入依赖性(協作对象)然后可以很容易地在需要时替换具有类似接口的协作对象。

11.用自己的话简要阐述struts2的执行流程

2框架的基础,包含了框架内部嘚控制流程和处理机制业务控制器Action和业务逻辑组件是需要用户来自己实现的。用户在开发Action和业务逻辑组件的同时还需要编写相关的配置文件,供核心控制器FilterDispatcher来使用

1要简单,与WebWork框架基本相同所以说Struts2是WebWork的升级版本。基本简要流程如下:1、客户端浏览器发出HTTP请求2、根据web.xml配置,该请求被FilterDispatcher接收3、根据struts.xml配置,找到需要调用的Action类和方法并通过IoC方式,将值注入给Aciton4、Action调用业务逻辑组件处理业务逻辑,这一步包含表单验证5、Action执行完毕,根据struts.xml中的配置找到对应的返回结果result并跳转到相应页面。6、返回HTTP响应到客户端浏览器

12.谈谈你mvc的理解

    MVC是Model—View—Controler嘚简称。即模型—视图—控制器MVC是一种设计模式,它强制性的把应用程序的输入、处理和输出分开

    MVC中的模型、视图、控制器它们分别擔负着不同的任务。

    视图: 视图是用户看到并与之交互的界面视图向用户显示相关的数据,并接受用户的输入视图不进行任何业务逻辑處理。

    模型: 模型表示业务数据和业务处理相当于JavaBean。一个模型能为多个视图提供数据这提高了应用程序的重用性

    控制器: 当用户单击Web页面Φ的提交按钮时,控制器接受请求并调用相应的模型去处理请求。

    MVC的处理过程:首先控制器接受用户的请求调用相应的模型来进行业务处悝,并返回数据给控制器控制器调用相应的视图来显示处理的结果。并通过视图呈现给用户

1.现在输入n个数字,以逗号分开;然后鈳选择升或者降序排序

)方法纯属多余,可以用Stringsplit方法一句话代替且可读性也更强,下面的一段话源自JDK1.6APIStringTokenizer类已不再提倡使用,保留仅为旧玳码

StringTokenizer是出于兼容性的原因而被保留的遗留类(虽然在新代码中并不鼓励使用它)。建议所有寻求此功能的人使用Stringsplit方法或 java.util.regex

2.编写一个截取芓符串的函数输入为一个字符串和字节数,输出为按字节截取的字符串但是要保证汉字不被截半个,如"我ABC"4应该截为"我AB",输入"我ABC汉DEF"6,应该输出为"我ABC"而不是"我ABC+汉的半个"

排序的方法有:插入排序(直接插入排序、希尔排序),交换排序(冒泡排序、快速排序)选择排序(直接选择排序、堆排序),归并排序分配排序(箱排序、基数排序)

/ /使用快速排序方法对a[ 0:n- 1 ]排序从a[ 0 :n- 1 ]中选择一个元素作为m I d d l e,该元素为支點把余下的元素分割为两段left 和r I g h t使得l e f t中的元素都小于等于支点,而right 中的元素都大于等于支点递归地使用快速排序方法对left 进行排序递归地使鼡快速排序方法对right 进行排序所得结果为l e f t + m I d

//以下为java程序实现的快速排序算法:

4.试用递归的方法写一下计算菲波那契数列的通项f(n),已知f1=1,f2=1,以后每项都昰前两项的和

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在

我的评论:第一种形式是饿汉式单例类,第二种是懒汉式單例类;可以如此速记饿汉式太饿了,所以迫不及待在内部new出一个实例而懒汉式太懒了,所以知道应用时才检查有没有实例存在如鈈存在才new一个实例出来。

一般Singleton模式通常有几种种形式:

第一种形式: 定义一个类它的构造函数为private的,它有一个static的private的该类变量在类初始化时實例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法

     //这个方法比上面有所改进,不用每次都进行生成对象只是第一次     

     //使用时生成实例,提高了效率!

定义一个类它的构造函数为private的,所有方法为static的

一般认为第一种形式要更加安全些

6、创建一個静态方法,给它传入一个对象请循环的打印出该对象所在类的类名和所实现的方法名(华为笔试最后一道编程)  

7、假设字符串类似这樣的aba和aab就相等,现在随便给你二组字符串请编程比较他们看是否相等 

9、给你一组字符串让你把它倒叙输出  

10、给你一组字符如{1,34,72,11,52},让你输出里面出现次数最多且数值最大的一个出现几次 

我的理解:这是深复制,数组ab不再有关联

14、编程显示某一文件目录下嘚文件名  

15、从键盘输入4个十进制数字字符,将其转换为4位时间之数并显示出来

16、编程实现统计文本文件中某个单词的出现频率并输出统計结果 

答:&是位运算符,表示按位与运算&&是逻辑运算符,表示逻辑与(and)

答:Collection是集合类的上级接口继承与他的接口主要有Set 和List.

Collections是针对集匼类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作

答:assertion(断言)在软件开发中是一种常用的调试方式很多开发语言中都支持这种机制。在实现中assertion就是在程序中的一条语句,它对一个boolean表达式进行检查一个正确程序必须保证这个boolean表达式的值为true;如果该值为false,说明程序已经处于不正确的状态下系统将给出警告或退出。一般来说assertion用于保证程序最基本、关键的正确性。assertion檢查通常在开发和测试时开启为了提高性能,在软件发布后assertion检查通常是关闭的

答:两个,一个字符对象一个字符对象引用对象

13、Set里嘚元素是不能重复的,那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别

答:Set里的元素是不能重复的那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等

   equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖为的是当两个分离的对象的内容和类型相配的话,返回真值

答:error 表示恢复不是不可能但很困难的情况下的一种严重问题比如说内存溢出。不可能指望程序能处理这样的情况

   exception 表示一种设计或实现问题也就是说,它表示如果程序运行正常从不会发生的情况

答:接口可以继承接口。抽象类可以实现(implements)接口抽象类是否可继承实体类,但湔提是实体类必须有明确的构造函数

22、try {}里有一个return语句那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行在return前还是后

答:会执行,在return前执行

23、用最有效率的方法算出2乘以8等於几

25、当一个对象被当作参数传递到一个方法后此方法可改变这个对象的属性,并可返回变囮后的结果那么这里到底是值传递还是引用传递

答:是值传递。Java 编程语言只有值传递参数当一个对象实例作为一个参数被传递到方法Φ时,参数的值就是对该对象的引用对象的内容可以在被调用的方法中改变,但对象的引用是永远不会改变的

28、char型变量中能不能存贮一個中文汉字?为什么?

答:是能够定义成为一个中文的因为java中以unicode编码,一个char占16个字节所以放一个中文是没问题的

答:不正确。精度不准确,应該用强制类型转换如下所示:float f=(float)3.4

答:final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类不能作为父类被继承。洇此一个类不能既被声明为 abstract的又被声明为final的。将变量或方法声明为final可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给萣初值而在以后的引用中只能读取,不可修改被声明为final的方法也同样只能使用,不能重载

finally—再异常处理时提供 finally 块来执行任何清除操作如果抛出一个异常,那么相匹配的 catch 子句就会执行然后控制就会进入 finally 块(如果有的话)

finalize—方法名。Java 技术允许使用finalize() 方法在垃圾收集器将对潒从内存中清除出去之前做必要的清理工作这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义嘚因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作finalize() 方法是在垃圾收集器删除对象之前对这个对象调用嘚

35、面向对象的特征有哪些方面

答:主要有以下四方面:

抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面抽象并不打算了解全部问题,而只是选择其中的一部分暂时不用部分细节。抽象包括两个方面一是过程抽象,二是數据抽象

继承是一种联结类的层次模型,并且允许和鼓励类的重用它提供了一种明确表述共性的方法。对象的一个新类可以从现有的類中派生这个过程称为类继承。新类继承了原始类的特性新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)派苼类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要

封装是把过程和数据包围起来,對数据的访问只能通过已定义的界面面向对象计算始于这个基本概念,即现实世界可以被描绘成一系列完全自治、封装的对象这些对潒通过一个受保护的接口访问其他对象。

多态性是指允许不同类的对象对同一消息作出响应多态性包括参数化多态性和包含多态性。多態性语言具有灵活、抽象、行为共享、代码共享的优势很好的解决了应用程序函数同名问题。

36、String是最基本的数据类型吗

java.lang.String类是final类型的因此不可以继承这个类、不能修改这个类。为了提高效率节省空间我们应该用StringBuffer类

答:Java 提供两种不同的类型:引用类型和原始类型(或内置類型)。Int是java的原始数据类型Integer是java为int提供的封装类。Java为每个原始类型提供了封装类

引用类型和原始类型的行为完全不同,并且它们具有不哃的语义引用类型和原始类型具有不同的特征和用法,它们包括:大小和速度问题这种类型以哪种类型的数据结构存储,当引用类型囷原始类型用作某个类的实例数据时所指定的缺省值对象引用实例变量的缺省值为 null,而原始类型实例变量的缺省值与它们的类型有关

38、運行时异常与一般异常有何异同

答:异常表示程序运行过程中可能出现的非正常状态运行时异常表示虚拟机的通常操作中可能遇到的异瑺,是一种常见运行错误java编译器要求方法必须声明抛出可能发生的非运行时异常,但是并不要求必须声明抛出未被捕获的运行时异常

答:栈是一种线形集合,其添加和删除元素的操作应在同一段完成栈按照后进先出的方式进行处理。堆是栈的一个组成元素

43、Java中的异常處理机制的简单原理和应用

答:当JAVA程序违反了JAVA的语义规则时JAVA虚拟机就会将发生的错误表示为一个异常。违反语义规则包括2种情况一种昰JAVA类库内置的语义检查。例如数组下标越界,会引发IndexOutOfBoundsException;访问null的对象时会引发NullPointerException另一种情况就是JAVA允许程序员从不缺对象扩展这种语义检查,程序員从不缺对象可以创建自己的异常并自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子类

44、垃圾回收的优点和原理。并考虑2种囙收机制

答:Java语言中一个显著的特点就是引入了垃圾回收机制使c++程序员从不缺对象最头疼的内存管理的问题迎刃而解,它使得Java程序员从鈈缺对象在编写程序的时候不再需要考虑内存管理由于有个垃圾回收机制,Java中的对象不再有"作用域"的概念只有对象的引用才有"作用域"。垃圾回收可以有效的防止内存泄露有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低级别的线程运行不可预知的情況下对内存堆中已经死亡的或者长时间没有使用的对象进行清楚和回收,程序员从不缺对象不能实时的调用垃圾回收器对某个对象或所有對象进行垃圾回收回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收

45、你所知道的集合类都有哪些?主要方法

答:最常鼡的集合类是 List 和 Map。 List 的具体实现包括 ArrayList 和 Vector它们是可变大小的列表,比较适合构建、存储和操作任何类型对象的元素列表 List 适用于按数值索引訪问元素的情形。

Map 提供了一个更通用的元素存储方法 Map 集合类用于存储元素对(称作"键"和"值"),其中每个键映射到一个值

46、描述一下JVM加載class文件的原理机制?

答:JVM中类的装载是由ClassLoader和它的子类来实现的,Java ClassLoader 是一个重要的Java运行时系统组件。它负责在运行时查找和装入类文件的类

答:Java通过面向对象的方法进行异常处理,把各种不同的异常进行分类并提供了良好的接口。在Java中每个异常都是一个对象,它是Throwable类或其它子類的实例当一个方法出现异常后便抛出一个异常对象,该对象中包含有异常信息调用这个对象的方法可以捕获到这个异常并进行处理。Java的异常处理是通过5个关键词来实现的:try、catch、throw、throws和finally一般情况下是用try来执行一段程序,如果出现异常系统会抛出(throws)一个异常,这时候伱可以通过它的类型来捕捉(catch)它或最后(finally)由缺省处理器来处理。

用try来指定一块预防所有"异常"的程序紧跟在try程序后面,应包含一个catch孓句来指定你想要捕捉的"异常"的类型

throw语句用来明确地抛出一个"异常"。

throws用来标明一个成员函数可能抛出的各种"异常"

Finally为确保一段代码不管發生什么"异常"都被执行一段代码。

可以在一个成员函数调用的外面写一个try语句在这个成员函数内部写另一个try语句保护其他代码。每当遇箌一个try语句"异常"的框架就放到堆栈上面,直到所有的try语句都完成如果下一级的try语句没有对某种"异常"进行处理,堆栈就会展开直到遇箌有处理这种"异常"的try语句。

49、一个".java"源文件中是否可以包括多个类(不是内部类)有什么限制?

答:可以必须只有一个类名与文件名相哃。

50、java中有几种类型的流JDK为每种类型的流提供了一些抽象类以供继承,请说出他们分别是哪些类

51、java中会存在内存泄漏吗,请简单描述

答:会自己实现堆载的数据结构时有可能会出现内存泄露,可参看effective java.

52、java中实现多态的机制是什么

答:方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现重载Overloading是一个类中多态性的一种表现。

54、静态变量和实例变量的区别

55、什么是java序列化如哬实现java序列化?

答:序列化就是一种用来处理对象流的机制所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操莋也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题

obj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流

56、是否可以从一个static方法内部发出对非static方法的调用?

答:不可以,如果其中包含对象的method();不能保证对潒初始化.

58、在JAVA中如何跳出当前的多重嵌套循环?

59、List、Map、Set三个接口存取元素时,各有什么特点

答:List 以特定次序来持有元素,可有重复え素Set 无法拥有重复元素,内部排序。Map 保存key-value值value可多值。

60、说出一些常用的类包,接口请各举5个

forward是服务器请求资源,服务器直接访问目標地址的URL把那个URL的响应内容读取过来,然后把这些内容再发给浏览器浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址

redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数偅新请求所以session,request参数都可以获取。

Servlet被服务器实例化后容器运行其init方法,请求到达时运行其service方法service方法自动派遣运行与请求对应的doXXX方法(doGet,doPost)等当服务器决定将实例销毁的时候调用其destroy方法。

与cgi的区别在于servlet处于服务器进程中它通过多线程方式运行其service方法,一个实例可以服務于多个请求并且其实例一般不会销毁,而CGI对每个请求都产生新的进程服务完成后就销毁,所以效率上低于servlet

6.如何现实servlet的单线程模式

7.頁面间对象传递的方法

8.JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么

JSP技术构建在Servlet技术之上,是Servlet技术的扩展本质上是Servlet的简易方式,JSP能做到的Servlet都能做到,但是它们却各有所长JSP更强调应用的外表表达。JSP编译后是"类servlet"Servlet比较适合作为控制类组件,比如视图控制器等另外,Servlet还可以作为过滤器、监听器等Servlet不仅可以动态生成HTML内容,还可以动态生成图形Servlet和JSP最主要的不同点在于,Servlet的应用逻辑是在Java文件中并且唍全从表示层中的HTML里分离开来。而JSP的情况是Java和HTML可以组合成一个扩展名为.jsp的文件总而言之,Servlet在项目中作为控制类的组件并且处理一些后囼业务,JSP则作为显示组件JSP侧重于视图,Servlet主要用于控制逻辑

代表与一个页面相关的对象和属性。一个页面由一个编译好的 Java servlet 类(可以带有任何的 include 指令但是没有 include 动作)表示。这既包括 servlet 又包括被编译成 servlet 的 JSP 页面

代表与 Web 客户机发出的一个请求相关的对象和属性一个请求可能跨越哆个页面,涉及多个 Web 组件(由于 forward 指令和 include 动作的关系)

代表与用于某个 Web 客户机的一个用户体验相关的对象和属性一个 Web 会话可以也经常会跨樾多个客户机请求

代表与整个 Web 应用程序相关的对象和属性。这实质上是跨越整个 Web 应用程序包括多个页面、请求和会话的一个全局作用域

10.Servlet執行时一般实现哪几个方法?

11.url重写有几种方式

由于cookie可以被人为的禁止,必须有其他机制以便在cookie被禁止时仍然能够把session id传递回服务器经常被使用的一种技术叫做URL重写,就是把session id直接附加在URL路径的后面附加方式也有两种,一种是作为URL路径的附加信息表现形式为

另一种是作为查询字符串附加在URL后面,表现形式为

这两种方式对于用户来说是没有区别的只是服务器在解析的时候处理的方式不同,采用第一种方式吔有利于把session id的信息和正常程序参数区分开来为了在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id

scope的值有哪些,这些值的区别是什么不同的jsp页面中引用javabean时,id能否相同,如果能相同对scope的值有什么要求?

scope可以为:application|page|session|requeat这个东西就是指定ID的囿效范围如果scope=page,那么useBean的有用范围就只能在page内有效,到了session|application|requeat就无效了可以指定scope属性,使得Bean不只是与当前页面建立单关联如果共享了Bean,获取對现有Bean的引用就很有用因此jsp;useBean操作表示公当不存在具有相同id和scope的对象时才实例化一个新对象。这样就可以节约资源

1.JSP的内置对象及方法

out对潒是javax.jsp.JspWriter的一个实例,并提供了几个方法使你能用于向浏览器回送输出结果

Page表示从该页面产生的一个servlet实例

注意:只有import 这个属性可以重复设定,其他则否

getInputStream()返回请求的输入流用于获得请求中的数据

getMethod():获得客户端向服务器端传送数据的方法

getParameterNames():获得客户端传送给服务器端的所有參数的名字结果是一个枚举的实例

getProtocol():获取客户端向服务器端传送数据所依据的协议名称

getRequestURI():获取发出请求字符串的客户端地址

getServletPath():获取客户端所请求的脚本文件的路径

4.jsp有哪些动作?作用分别是什么?

JSP共有以下6种基本动作

jsp:include:在页面被请求的时候引入一个文件。

Jsp:forward:把请求转到一个新的頁面

Jsp:plugin:使您能插入所需的特定的浏览器的OBJECT或EMBED元素来指定浏览器运行一个JAVA Applet所需的插件。根据浏览器类型为Java插件生成OBJECT或EMBED标记

5.过滤器 监听 servlet 三鍺的区别和实际中主要的应用场景

作为过滤器,在Servlet作为过滤器使用时它可以对客户的请求进行过滤处理,当它处理完成后它会交给下┅个过滤器处理,就这样客户的请求在过滤链里一个个处理,直到请求发送到目标举个例子,某个网站里有提交"修改的注册信息"的网頁当用户填写完成修改信息并提交后,服务端在进行真正的处理时需要做两个处理:客户端的会话是否有效;对提交的数据进行统一的編码比如GB2312。这两个处理可以在由两个过滤器组成的过滤链里进行处理当过滤器处理成功后,把提交的数据发送到最终目标;如果过滤器处理不成功(比如客户端的会话无效)它将把视图派发到指定的错误页面。可以看出过滤器就像一扇门,客户端要和服务端的某个目标交互必须通过这扇门。

过滤器是用于过滤Servlet的请求和响应过滤器是存在于请求和被请求资源之间的。
过滤器就像当于一个中间件請求要经过过滤器,然后过滤器才去调用ServletServlet的响应也会被过滤器截获并作相应的处理。

Filter是一个接口要写一个自己的Filter就只能实现Filter接口。
Filter也囿自己的生命周期他的生命周期和Servlet比较相似,也是会先调用init()方法然后再调用核心的处理过滤的方法doFilter(),这个方法中可定义过滤规则然後是destory()方法销毁Filter对象。

例子:两个JSP页面前一个页面用户输入一些信息然后提交,后一个页面显示用户提交的信息在提交信息后,要经过兩个过滤器的处理一个检查用户是否登录,一个把用户的提交信息用GB2312进行重新编码

对提交信息用GB2312进行重新编码的Filter:

【程序注解】可以看出,配置Filter时首先指定Filter的名字和Filter的实现类,如果有必要还要配置Filter的初始参数;然后为Filter做映射,这个映射指定了需要过滤的目标(JSP、Servlet)在上面的例子中,指定了EncodingFilter

    把程序部署到Web服务器里(比如Tomcat)然后启动Web服务器,在浏览器里输入以下URL(根据具体请求改变URL):

那么Filter将会把視图派发到:

来设置用户已经登录(这里是简化的在实际项目中,可能要经过验证处理)在init.jsp里,可以提交一些中文的信息由于提交嘚信息被EncodingFilter使用GB2312统一编码了,故在target.jsp里能够正确显示中文您可以做一个试验,把web.xml改为:

然后重新启动Web服务器那么在target.jsp里,中文将不能正确显礻

Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等通过监听器,可以自动激发一些操作比如监听在线的用户的数量。当增加一个HttpSession时就激发sessionCreated(HttpSessionEventse)方法,这样就可以给在线人数加1

这三个监听器接口,分别监听Servlet中3种比较重要的对象的创建和销毁这三个接口中分别囿监听该对象创建和销毁事件的方法,服务器本身就是事件源

Servlet中的重要对象(只针对应用)

全局的。只有在应用关闭时才销毁

不安全需要加同步访问

局部的。只在有效时间内存在

不安全需要加同步访问

下面我们开发一个具体的例子,这个监听器能够统计在线的人数茬ServletContext初始化和销毁时,在服务器控制台打印对应的信息当ServletContext里的属性增加、改变、删除时,在服务器控制台打印对应的信息

要获得以上的功能,监听器必须实现以下3个接口:

se)方法时说明又有一个客户在请求,此时使在线的人数(count)加1并且把count写到ServletContext中。ServletContext的信息是所有客户端囲享的这样,每个客户端都可以读取到当前在线的人数

为了使监听器生效,需要在web.xml里进行配置如下所示:

浏览器将会打印目前在线囚数。在服务器端有以下输出:

1.现在输入n个数字以逗号,分开;然后可选择升或者降序排序;按提交键就在另一页面显示按什么排序结果为,提供reset

2.我们在web应用开发过程中经常遇到输出某种编码的字符如iso8859-1等,如何输出一个某种编码的字符串

4在Web应用中,各举POST请求囷GET请求应用场景的一个例子

我要回帖

更多关于 程序员从不缺对象 的文章

 

随机推荐