- java概述
- 什么是B/S架构?什么是C/S架构
- Java都有那些开发平台?
- 关于 JVM JDK 和 JRE 最详细通俗的解答
- 什么是字节码?采用字节码的好处是什么?
- Java程序从源代码到运行一般有下面3 步:
- 什么是Java
- Java语言有哪些特点
- 什么是Java程序的主类?应用程序和小程序的主类有何不同?
- Java和C++的区别
- JAVA创建对象的几种方式
- Java中Object类常用方法
- 什么是java序列化,如何实现java序列化?或者请解释Serializable接口的作用。
- 为什么有些java类要实现Serializable接口
- 除了实现Serializable接口还有什么序列化方式**
- instanceof 关键字的作用
- import java和javax有什么区别?
- 为什么说Java语言“编译与解释并存”?
- 基础语法
- Java有哪些数据类型
- Java的基本数据类型(及包装类型)都有哪些各占几个字节?
- int和Integer有什么区别?
- 下面 Integer 类型的数值比较输出的结果为?
- 数据类型之间如何进行转换?
- 标识符的命名规则
- switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上
- 用最有效率的方法计算 2 乘以 8
- Math.round(11.5) 等于多少?Math.round(-11.5)等于多少
- 基本数据类型在 Java虚拟机中一定存储在栈中吗?为什么?
- float f=3.4;是否正确
- short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗
- **能将** **int** **强制转换为** **byte** **类型的变量吗?如果该值大于** **byte** **类**型的范围,将会出现什么现象?
- Java语言采用何种编码方案?有何特点?
- &和&&的区别
- 访问修饰符 public,private,protected,以及不写(默认)时的区别
- 关键字
- 变量命名有哪些规则
- break,continue,return 有什么区别
- final,finally和finalize有什么区别
- assert(断言)有什么作用
- static关键字有哪些作用
- 使用switch时有哪些注意事项
- volatile有什么作用
- Java 有没有 goto
- final 有什么用?
- final finally finalize区别
- this关键字的用法
- super和this的区别
- 面向对象
- 面向对象的特征有哪些方面
- 其中Java 面向对象编程三大特性:封装 继承 多态
- 什么是多态机制?Java语言是如何实现多态的?
- 值传递和引用传递有什么区别?Java中参数是什么传递方式?
- Java实现多态有三个必要条件:继承、重写、向上转型。
- 重载和重写有什么区别?
- 构造器能被重写吗?
- 面向对象五大基本原则是什么
- 类与抽象类和接口
- 一个类实现了多个接口中的重名默认方法,调用时会使用哪个?
- 抽象类能用final修饰吗?
- 普通类和抽象类有哪些区别?
- 创建一个对象用什么关键字?对象实例与对象引用有何不同?
- 变量与方法
- 成员变量与局部变量的区别有哪些
- 在Java中定义一个不做事且没有参数的构造方法的作用
- 在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?
- 一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?
- 构造方法有哪些特性?
- 静态变量和实例变量区别
- 静态变量与普通变量区别
- 静态方法和实例方法有何不同?
- 在一个静态方法内调用一个非静态成员为什么是非法的?
- 什么是方法的返回值?返回值的作用是什么?
- Java泛型面试题
- Java中的泛型是什么 ? 使用泛型的好处是什么?
- Java的泛型是如何工作的 ? 什么是类型擦除 ?
- 什么是泛型中的限定通配符和非限定通配符 ?
- List extends T>和List super T>之间有什么区别 ?
- 如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?
- Java中如何使用泛型编写带有参数的类?
- 编写一段泛型程序来实现LRU缓存?
- Array中可以用泛型吗?
- 内部类
- 什么是内部类?
- 内部类的分类有哪些
- 静态内部类特点
- 成员内部类
- 局部内部类
- 局部内部类特点
- 匿名内部类
- 匿名内部类还有以下特点:
- 匿名内部类包括以下部分:
- 匿名内部类的访问权限 :
- 我们为什么要使用内部类呢?因为它有以下优点:
- 内部类有哪些应用场景
- 局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?
- 重写与重载
- 构造器(constructor)是否可被重写(override)
- 重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?
- == 和 equals 的区别是什么
- hashCode 与 equals (重要)
- 为什么要有 hashCode
- hashCode()与equals()的相关规定
- 对象的相等与指向他们的引用相等,两者有什么不同?
- java只有值传递
- 枚举类
- **枚举类中的声明**
- Java枚举类的使用规则
- IO流
- 什么是比特(Bit)?什么是字节(Byte)?什么是字符(Char)?以及他们的区别?
- IO流的概念:什么是IO流?
- java 中 IO 流分为几种?
- B/S(Browser/Server),浏览器/服务器程序
- C/S(Client/Server),客户端/服务端,桌面应用程序
- JAVA SE:主要用在客户端开发
- JAVA EE:主要用在web应用程序开发
- JAVA ME:主要用在嵌入式应用程序开发
Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows, Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。
什么是字节码?采用字节码的好处是什么?在 Java 中,JVM 可以理解的代码就叫做 字节码 (即扩展名为 .class 的文件),它不面向任何 特定的处理器,只面向虚拟机。Java 语言通过字节码的方式,在一定程度上解决了传统解释型语 言执行效率低的问题,同时又保留了解释型语言可移植的特点。所以 Java 程序运行时比较高效, 而且,由于字节码并不针对一种特定的机器,因此,Java 程序无须重新编译便可在多种不同操作 系统的计算机上运行。
Java程序从源代码到运行一般有下面3 步:我们需要格外注意的是 .class->机器码 这一步。在这一步 JVM 类加载器首先加载字节码文件,然后通过 解释器逐行解释执行,这种方式的执行速度会相对比较慢。而且,有些方法和代码块是经常需要被调用 的(也就是所谓的热点代码),所以后面引进了 JIT 编译器,而 JIT 属于运行时编译。当 JIT 编译器完成第 一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效 率肯定是高于 Java 解释器的。这也解释了我们为什么经常会说 Java 是编译与解释共存的语言。
HotSpot 采用了惰性评估(Lazy Evaluation)的做法,根据二八定律,消耗大部分系统资源的只有 那一小部分的代码(热点代码),而这也就是 JIT 所需要编译的部分。JVM 会根据代码每次被执行 的情况收集信息并相应地做出一些优化,因此执行的次数越多,它的速度就越快。JDK 9 引入了 一种新的编译模式 AOT(Ahead of Time Compilation),它是直接将字节码编译成机器码,这样就 避免了 JIT 预热等各方面的开销。JDK 支持分层编译和 AOT 协作使用。但是 ,AOT 编译器的编译 质量是肯定比不上 JIT 编译器的。
总结:
Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows, Linux,macOS),目的是使用相同的字节码,它们都会给出相同的结果。字节码和不同系统的 JVM 实 现是 Java 语言“一次编译,随处可以运行”的关键所在。
JDK 和 **JRE
** JDK 是 Java Development Kit,它是功能齐全的 Java SDK。它拥有 JRE 所拥有的一切,还有编译器
(javac)和工具(如 javadoc 和 jdb)。它能够创建和编译程序。
JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机
(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。
如果你只是为了运行一下 Java 程序的话,那么你只需要安装 JRE 就可以了。如果你需要进行一些 Java 编程方面的工作,那么你就需要安装 JDK 了。但是,这不是绝对的。有时,即使您不打算在计算机上进 行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲, 您只是在应用程序服务器中运行 Java 程序。那你为什么需要 JDK 呢?因为应用程序服务器会将 JSP 转 换为 Java servlet,并且需要使用 JDK 来编译 servlet。
Oracle JDK 和 OpenJDK **的对比
** 可能在看这个问题之前很多人和我一样并没有接触和使用过 OpenJDK 。那么 Oracle 和 OpenJDK 之间
是否存在重大差异?下面我通过收集到的一些资料,为你解答这个被很多人忽视的问题。
对于 Java 7,没什么关键的地方。OpenJDK 项目主要基于 Sun 捐赠的 HotSpot 源代码。此外, OpenJDK 被选为 Java 7 的参考实现,由 Oracle 工程师维护。关于 JVM,JDK,JRE 和 OpenJDK 之间的 区别,Oracle 博客帖子在 2012 年有一个更详细的答案:
问:OpenJDK 存储库中的源代码与用于构建 Oracle JDK 的代码之间有什么区别?
答:非常接近 - 我们的 Oracle JDK 版本构建过程基于 OpenJDK 7 构建,只添加了几个部分,例 如部署代码,其中包括 Oracle 的 Java 插件和 Java WebStart 的实现,以及一些封闭的源代码派 对组件,如图形光栅化器,一些开源的第三方组件,如 Rhino,以及一些零碎的东西,如附加文 档或第三方字体。展望未来,我们的目的是开源 Oracle JDK 的所有部分,除了我们考虑商业功能 的部分。
总结:
-
Oracle JDK 大概每 6 个月发一次主要版本,而 OpenJDK 版本大概每三个月发布一次。但这不是固 定的,我觉得了解这个没啥用处。
-
OpenJDK 是一个参考模型并且是完全开源的,而 Oracle JDK 是 OpenJDK 的一个实现,并不是完 全开源的;
-
Oracle JDK 比 OpenJDK 更稳定。OpenJDK 和 Oracle JDK 的代码几乎相同,但 Oracle JDK 有更 多的类和一些错误修复。因此,如果您想开发企业/商业软件,我建议您选择 Oracle JDK,因为它 经过了彻底的测试和稳定。某些情况下,有些人提到在使用 OpenJDK 可能会遇到了许多应用程序 崩溃的问题,但是,只需切换到 Oracle JDK 就可以解决问题;
-
在响应性和 JVM 性能方面,Oracle JDK 与 OpenJDK 相比提供了更好的性能;
-
Oracle JDK 不会为即将发布的版本提供长期支持,用户每次都必须通过更新到最新版本获得支持
来获取最新版本;
-
Oracle JDK 根据二进制代码许可协议获得许可,而 OpenJDK 根据 GPL v2 许可获得许可。
Java是一门面向对象的高级编程语言,不仅吸收了C++语言的各种优点,比如继承了C++语言面向对象的技术核心。还摒弃了C++里难以理解的多继承、指针等概念,同时也增加了垃圾回收机制,释放掉不 被使用的内存空间,解决了管理内存空间的烦恼。
因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地 实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。
什么是跨平台性?原理是什么
所谓跨平台性,是指java语言编写的程序,一次编译后,可以在多个系统平台上运行。
实现原理:Java程序是通过java虚拟机在系统平台上运行的,只要该系统可以安装相应的java虚拟机,该系统就可以运行java程序。
Java语言有哪些特点Java 语言是一种分布式的面向对象语言,具有面向对象、平台无关性、简单性、解释执行、多线程、安全性等很多特点,下面针对这些特点进行逐一介绍。
1. 面向对象
Java 是一种面向对象的语言,它对对象中的类、对象、继承、封装、多态、接口、包等均有很好的支 持。为了简单起见,Java 只支持类之间的单继承,但是可以使用接口来实现多继承。使用 Java 语言开发 程序,需要采用面向对象的思想设计程序和编写代码。
2. 平台无关性
平台无关性的具体表现在于,Java 是“一次编写,到处运行(Write Once,Run any Where)”的语言, 因此采用 Java 语言编写的程序具有很好的可移植性,而保证这一点的正是 Java 的虚拟机机制。在引入 虚拟机之后,Java 语言在不同的平台上运行不需要重新编译。
Java 语言使用 Java 虚拟机机制屏蔽了具体平台的相关信息,使得 Java 语言编译的程序只需生成虚拟机 上的目标代码,就可以在多种平台上不加修改地运行。
3. 简单性
Java 语言的语法与 C 语言和 C++ 语言很相近,使得很多程序员学起来很容易。对 Java 来说,它舍弃了 很多 C++ 中难以理解的特性,如操作符的重载和多继承等,而且 Java 语言不使用指针,加入了垃圾回 收机制,解决了程序员需要管理内存的问题,使编程变得更加简单。
4. 解释执行
Java 程序在 Java 平台运行时会被编译成字节码文件,然后可以在有 Java 环境的操作系统上运行。在运 行文件时,Java 的解释器对这些字节码进行解释执行,执行过程中需要加入的类在连接阶段被载入到运 行环境中。
5. 多线程
Java 语言是多线程的,这也是 Java 语言的一大特性,它必须由 Thread 类和它的子类来创建。Java 支持 多个线程同时执行,并提供多线程之间的同步机制。任何一个线程都有自己的 run() 方法,要执行的方 法就写在 run() 方法体内。
6. 分布式
Java 语言支持 Internet 应用的开发,在 Java 的基本应用编程接口中就有一个网络应用编程接口,它提 供了网络应用编程的类库,包括 URL、URLConnection、Socket 等。Java 的 RIM 机制也是开发分布式 应用的重要手段。
7. **健壮性
** Java 的强类型机制、异常处理、垃圾回收机制等都是 Java 健壮性的重要保证。对指针的丢弃是 Java 的
一大进步。另外,Java 的异常机制也是健壮性的一大体现。
8. 高性能
Java 的高性能主要是相对其他高级脚本语言来说的,随着 JIT(Just in Time)的发展,Java 的运行速度 也越来越高。
9. 安全性
Java 通常被用在网络环境中,为此,Java 提供了一个安全机制以防止恶意代码的攻击。除了 Java 语言 具有许多的安全特性以外,Java 还对通过网络下载的类增加一个安全防范机制,分配不同的名字空间以 防替代本地的同名类,并包含安全管理机制。
Java 语言的众多特性使其在众多的编程语言中占有较大的市场份额,Java 语言对对象的支持和强大的 API 使得编程工作变得更加容易和快捷,大大降低了程序的开发成本。Java 的“一次编写,到处执行”正是 它吸引众多商家和编程人员的一大优势。
什么是Java程序的主类?应用程序和小程序的主类有何不同?一个程序中可以有多个类,但只能有一个类是主类。在Java应用程序中,这个主类是指包含main()方法的类。而在Java小程序中,这个主类是一个继承自系统类JApplet或Applet的子类。应用程序的主类不一定要求是public类,但小程序的主类要求必须是public类。主类是Java程序执行的入口点。
Java应用程序与小程序之间有那些差别?
简单说应用程序是从主线程启动(也就是main()方法)。applet小程序没有main方法,主要是嵌在浏览器页面上运行(调用init()线程或者run()来启动),嵌入浏览器这点跟flash的小游戏类似。
Java和C++的区别我知道很多人没学过C++,但是面试官就是没事喜欢拿咱们Java和C++比呀!没办法!!!就算没学过C++,也要记下来!
都是面向对象的语言,都支持封装、继承和多态
Java不提供指针来直接访问内存,程序内存更加安全
Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是接口可以多继承。
Java有自动内存管理机制,不需要程序员手动释放无用内存
1、用new关键字创建对象,需要使用构造器。
2、使用反射机制创建对象,用Class类或Constructor类的newInstance()方法。需要使用构造器。当使用Class类里的newInstance()方法,调用的是无参构造方法。当使用java.lang.reflect.Constructor类里的newInstance方法,调用的是有参构造方法。
3、通过object类的clone方法
需要实现Cloneable接口,重写object类的clone方法。无论何时我们调用一个对象的clone方法,JVM就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
4、使用反序列化
通过ObjectInputStream的readObject()方法反序列化类当我们序列化和反序列化一个对象,JVM会给我们创建一个单独的对象。为了反序列化一个对象,我们需要让我们的类实现Serializable接口。在反序列化时,JVM创建对象并不会调用任何构造函数。
Java中Object类常用方法Object 是 Java 类库中的一个特殊类,也是所有类的父类。当一个类被定义后,如果没有指定继承的父类,那么默认父类就是 Object 类。由于 Java 中的所有类都是由 Object 类派生出来的,因此在 Object 类中定义的方法,在其他类中都可以使用。
| Object clone() | 创建与该对象的类相同的新对象 |
|---|---|
| boolean equals(Object) | 比较两对象是否相等 |
| void finalize() | 当垃圾回收器确定不存在对该对象的更多引用时,对象垃圾回收器调用该方法 |
| Class getClass() | 返回一个对象运行时的实例类 |
| int hashCode() | 返回该对象的散列码值 |
| void notify() | 激活等待在该对象的监视器上的一个线程 |
| void notifyAll() | 激活等待在该对象的监视器上的全部线程 |
| String toString() | 返回该对象的字符串表示 |
| void wait() | 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待 |
我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如, 要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java 对象变成某个格式的字节流再传输。
但是,jre本身就提供了这种支持,我们可以调用 OutputStream 的 writeObject 方法来做,如果要让 java帮我们做,要被传输的对象必须实现 serializable 接口,这样,javac编译时就会进行特殊处理, 编译的类才可以被 writeObject 方法操作,这就是所谓的序列化。需要被序列化的类必须实现
Serializable 接口,该接口是一个mini接口,其中没有需要实现方法,implements Serializable只是 为了标注该对象是可被序列化的。
为什么有些java类要实现Serializable接口为了网络进行传输或者持久化
什么是序列化
将对象的状态信息转换为可以存储或传输的形式的过程
除了实现Serializable接口还有什么序列化方式**Json序列化 FastJson序列化 ProtoBuff序列化
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);import java和javax有什么区别?
刚开始的时候 JavaAPI 所必需的包是 java 开头的包,javax 当时只是扩展 API 包来使用。然而随着时间的推移,javax 逐渐地扩展成为 Java API 的组成部分。但是,将扩展从 javax 包移动到 java 包确实太麻烦了,最终会破坏一堆现有的代码。因此,最终决定 javax 包将成为标准 API 的一部分。
所以,实际上 java 和 javax 没有区别。这都是一个名字。
为什么说Java语言“编译与解释并存”?高级编程语言按照程序的执行方式分为编译型和解释型两种。简单来说,编译型语言是指编译器针对特
定的操作系统将源代码一次性翻译成可被该平台执行的机器码;解释型语言是指解释器对源程序逐行解
释成特定平台的机器码并立即执行。比如,你想阅读一本英文名著,你可以找一个英文翻译人员帮助你
阅读,有两种选择方式,你可以先等翻译人员将全本的英文名著(也就是源码)都翻译成汉语,再去阅读,也
可以让翻译人员翻译一段,你在旁边阅读一段,慢慢把书读完。
Java 语言既具有编译型语言的特征,也具有解释型语言的特征,因为 Java 程序要经过先编译,后解释 两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(*.class 文件),这种字节码必须由 Java 解释器来解释执行。因此,我们可以认为 Java 语言编译与解释并存。
基础语法 Java有哪些数据类型Java中有 8 种基本数据类型,分别为:
6 种数字类型 (四个整数形,两个浮点型):byte、short、int、long、float、double
1 种字符类型:char
1 种布尔型:boolean。
**byte ** :
byte 数据类型是8位、有符号的,以二进制补码表示的整数; 最小值是 -128(-2^7);
最大值是 127(2^7-1);
默认值是 0;byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的 四分之一;
short :
short 数据类型是 16 位、有符号的以二进制补码表示的整数
最小值是 -32768 ( -2^15 );
最大值是 32767 ( 2^15 - 1 );
Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一; 默认值是 0;
int :
int 数据类型是32位、有符号的以二进制补码表示的整数; 最小值是 -2,147,483,648 ( -2^31**)**;
最大值是 **2,147,483,647 ( 2^31 - 1 ); 一般地整型变量默认为 int 类型;默认值是 0 ;
long :
注意: Java 里使用 long 类型的数据一定要在数值后面加上 L ,否则将作为整型解析 long 数据类型是 64 位、有符号的以二进制补码表示的整数;
最小值是 -9,223,372,036,854,775,808 ( -2^63 );
最大值是 9,223,372,036,854,775,807 ( 2^63 -1 ); 这种类型主要使用在需要比较大整数的系统上;默认值是 0L;
float :
float 数据类型是单精度、32位、符合IEEE 754标准的浮点数; float 在储存大型浮点数组的时候可节省内存;
默认值是 0.0f;
浮点数不能用来表示精确的值,如货币;
double :
double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数; 浮点数的默认类型为double类型; double类型同样不能表示精确的值,如货币;
默认值是 0.0d;
char :
char类型是一个单一的 16 位 Unicode 字符; 最小值是 u0000(即为 0);
最大值是 uffff(即为 65535);
char 数据类型可以储存任何字符;
boolean :
boolean数据类型表示一位的信息; 只有两个取值:true 和 false; 这种类型只作为一种标志来记录 true/false 情况; 默认值是 false;
这八种基本类型都有对应的包装类分别为: Byte 、 Short 、 Integer 、 Long 、 Float 、 Double 、 Character 、 Boolean
Java的基本数据类型(及包装类型)都有哪些各占几个字节?- 基本数据类型:byte、 short、 int、 long、float、 double、boolean、 char
- 对应包装类型:Byte、Short、Integer、Long、Float、Double、Boolean、Character
- 各自所占字节数:1 2 4 8 4 8 1 2
java 是一个完全面向对象编程语言,但是为了编程的方便还是引入了基本数据类型,为了能够将这些基本数据类型当成对象操作,Java 为每一个基本数据类型都引入了对应的包装类型(wrapper class),int 的包装类就是Integer,从 Java 5 开始引入了 自动装箱/拆箱 机制,使得二者可以相互转换。
java 为每个原始类型提供了包装类型:
● 基本数据类型: boolean,char,byte,short,int,long,float,double
● 包装类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
public static void main(String[] args) {
Integer x=500;
System.out.println(x);
int y=x;
System.out.println(y);
Integer z=1000;
System.out.println(z+1);
}
下面 Integer 类型的数值比较输出的结果为?
public static void main(String[] args) {
Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
System.out.println(f1 == f2);//true
System.out.println(f3 == f4);//false
}
//首先需要注意的是 f1、f2、f3、f4 四个变量都是 Integer 对象引用,
//所以下面的==运算比较的不是值而是引用。这里就要提到自动装箱机制了,
//那么自动装箱的本质是什么呢?当我们给一个Integer 对象赋一个 int 值的时候,
//会调用 Integer 类的静态方法 valueOf,如果看看valueOf的源代码就知道发生了什么。
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
IntegerCache 是 Integer 的内部类,其代码如下所示:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
// Load IntegerCache.archivedCache from archive, if possible
VM.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
数据类型之间如何进行转换?
● 字符串如何转基本数据类型?
调用基本数据类型对应的包装类中的方法 parseXXX(String)或valueOf(String)即可返回相应基本类型。
● 基本数据类型如何转字符串?
一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;
另一种方法是调用 String类中的 valueOf()方法返回相应字符串。
标识符的命名规则标识符的含义: 是指在程序中,我们自己定义的内容,譬如,类的名字,方法名称以及变量名称等等,都是标识符。
命名规则:(硬性要求) 标识符可以包含英文字母,0-9的数字,$以及_ 标识符不能以数字开头 标 识符不是关键字
命名规范:(非硬性要求) 类名规范:首字符大写,后面每个单词首字母大写(大驼峰式)。 变量 名规范:首字母小写,后面每个单词首字母大写(小驼峰式)。 方法名规范:同变量名。
switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上在 Java 5 以前,switch(expr)中,expr 只能是 byte、short、char、int。从 Java5 开始,Java 中引入了枚举类型,expr 也可以是 enum 类型,从 Java 7 开始,expr 还可以是字符串(String),但是长整型(long)在目前所有的版本中都是不可以的。
用最有效率的方法计算 2 乘以 82 << 3(左移 3 位相当于乘以 2 的 3 次方,右移 3 位相当于除以 2 的 3 次方)。
Math.round(11.5) 等于多少?Math.round(-11.5)等于多少Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。四舍五入的原理是在参数上加 0.5 然后进行下取整。
基本数据类型在 Java虚拟机中一定存储在栈中吗?为什么?不对,基本数据类型不一定存储在栈中,因为基本类型的存储位置取决于声明的作用域,来看具体的解释。
- 当基本数据类型为局部变量的时候,比如在方法中声明的变量,则存放在方法栈中的,当方法结束系统会释放方法栈,在该方法中的变量也会随着栈的销毁而结束,这也是局部变量只能在方法中使用的原因;
- 当基本数据类型为全局变量的时候,比如类中的声明的变量,则存储在堆上,因为全局变量不会随着某个方法的执行结束而销毁。
不正确。3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化)会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F;。
short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给 short 型。而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。
能将 int 强制转换为 byte 类型的变量吗?如果该值大于 byte 类型的范围,将会出现什么现象?我们可以做强制转换,但是 Java 中 int 是 32 位的,而 byte 是 8 位的,所以,如果强制转化,int 类型 的高 24 位将会被丢弃,因为byte 类型的范围是从 -128 到 127
Java语言采用何种编码方案?有何特点?Java语言采用Unicode编码标准,Unicode(标准码),它为每个字符制订了一个唯一的数值,因此在任何的语言,平台,程序都可以放心的使用。
&和&&的区别&运算符有两种用法:(1)按位与;(2)逻辑与。
&&运算符是短路与运算。逻辑与跟短路与的差别是非常巨大的,虽然二者都要求运算符左右两端的布尔值都是true 整个表达式的值才是 true。&&之所以称为短路运算,是因为如果&&左边的表达式的值是 false,右边的表达式会被直接短路掉,不会进行运算。
注意:逻辑或运算符(|)和短路或运算符(||)的差别也是如此。
访问修饰符 public,private,protected,以及不写(默认)时的区别| 修饰符 | 当前类 | 同包 | 子类 | 其他包 |
|---|---|---|---|---|
| public | 能 | 能 | 能 | 能 |
| protected | 能 | 能 | 能 | 不能 |
| default | 能 | 能 | 不能 | 不能 |
| private | 能 | 不能 | 不能 | 不能 |
类的成员不写访问修饰时默认为 default。默认对于同一个包中的其他类相当于公 开(public),对于不是同一个包中的其他类相当于私有 (private)。受保护 (protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私 有。Java 中,外部类的修饰符只能 是 public 或默认,类的成员(包括内部类)的 修饰符可以是以上四种。
关键字 变量命名有哪些规则由数字,字母,_,$组成,且开头不能是数字
break,continue,return 有什么区别break:跳出当前循环
continue:跳出本次循环
return:从一个方法返回
final:用于修饰属性,方法,类,分别表示属性不可变(针对引用类型的属性指的是引用不可变,但对象中的数据可以变),方法不可覆盖,类不可继承
final成员变量必须初始化
定义时初始化,
final成员变量可以在初始化块中初始化,不能在静态初始化块中初始化
静态final成员变量可以在静态初始化块中初始化,但不能在初始化块中初始化
在构造器中初始化,但静态final变量不能在构造器中初始化
final类(如String,StringBuffer)
assert(断言)有什么作用不能继承,所有方法不能重写
final类的成员变量可以改变
一个类不能被final和abstract同时修饰
finally作为异常处理的一部分,表示这段语句最终一定会执行,经常用于释放资源
finalize是Object的一个方法,垃圾回收器执行时会调用被回收对象的finalize方法
一种软件调试方法,assert 表达式 ,若表达式为true正常运行,若false,则说明程序已经处于一种不正确的状态,系统需要提供告警信息并退出程序,同参在程序开发和测试时使用。
static关键字有哪些作用主要有两个作用:
-
static的主要意义是在于创建独立于具体对象的域变量或者方法。以致于即使没有创建对象,也能使用属性和调用方法!。具体而言使用static有四种情况:成员变量,成员方法,代码块,内部类
-
static成员变量
java中没有全局变量的概念,但可以通过static实现全局的效果,实例变量属于对象,对象创建后才为其开辟空间,静态变量属于类,类加载时就被分配了空间,可直接通过(类.静态变量)使用。
静态变量只有一份,不会随对象的多少发生改变,所有对象共享其静态变量 -
static成员方法
普通方法归属于对象,通过对象.方法调用,静态方法归属于类,通过类名.方法调用
静态方法中不能使用this,super关键字,只能使用静态变量或方法(因为此时可能还没有创建对象)
static有个重要的作用就是实现单例,将构造器声明为private的,在提供一个可获得对象的静态方法,可确保在程序运行时,该类的实例只有一份
public static的变量和方法本质上是全局的,若使用private static则表示在该类的静态代码块或类的静态方法中可以调用,不能在其他地方调用 -
static代码块
public calss PreCache{ static{ //执行相关操作 } }static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
-
static内部类
可以不依赖外部实例而实例化
只能调用静态变量或静态方法
static final修饰变量表示全局常量,一旦赋值不可修改,static final修饰方法表示该方法不可覆盖,且可通过类名访问
使用switch(expr)时,expre只能是一个枚举常量或一个整数表达式,不能是浮点类型的数据,jdk7以后expre也可以是String类型的,case后一定不能跟变量,或带有变量的表达式(final修饰的可以),case子句一般跟break配合,若没有break,程序会将符合条件的case,包括之下的case语句
volatile有什么作用为了提高运行效率,编译器会自动对其优化,将经常被访问到的数据缓存起来,但这样会带来线程安全问题,比如一个线程修改了数据,但缓存中没有即时对应修改,就会造成后来访问该数据的线程读到错误数据,使用volatile可以阻止数据进行缓存,保证线程安全,但这样做会影响性能,能不用就不用
Java 有没有 gotogoto 是 Java 中的保留字,在目前版本的 Java 中没有使用。
final 有什么用?用于修饰类、属性和方法;
如果一个类被声明为final,就意味着它不能再派生出新的子类,不能作为父类被继承。因此,一个类不能同时被abstract和final修饰,被final修饰的类不能做为父类被继承但是它却可以继承其它的类。
如果一个方法被声明为final,那么该方法是不能被重写的,因此一个方法也不能同时被abstract和final修饰,被final修饰的方法可以被子类继承。
被声明为final的变量必须要进行初始化,而在以后的引用中只能读取,不可修改。
final变量未被初始化,编译时就会报错,非静态final变量初始化可以是直接赋值、代码块赋值、构造函数赋值
,静态final变量初始化可以通过直接赋值、静态代码块赋值
final是java关键字,用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承。
finally是java中异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,如果子类中重写了该方法,在垃圾收集器执行的时候会调用被回收对象的此方法。
this关键字的用法java中this关键字必须放在非静态方法里面,this关键字代表自身,在程序中主要的用途有以下几个方面:
this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。
用法一:this.属性名
this表示当前类,this.属性名可以给当前类的属性赋值,可以在本类中除静态方法外的任何方法(包括构造器、私有方法)中使用,这里要注意static的特性(1.遵循静态调用 2·stati关键字不能与this、super关键字共用)。
另外,若本类成员变量与方法内局部变量同名,this.属性名代表的是什么呢??
当然是局部变量了,因为Java遵循就近原则,通俗地讲,就是谁离我近,我就代表谁。
代码实现:
class Student{
String name;
public void hello(){
this.name=name;
}
}
用法二:this.方法
这里比较好理解,this代表本类,this.方法即调用方法,除了静态方法中不可使用,本类其他方法包括私有方法均可使用此格式调用其他方法,只是我们通常省略this关键字。
代码实现:
class Student{
String name;
public void hello(){
this.name=name;
}
// this.name=name;this需要在方法内使用
public void hi(){
this.hello();
hello();
he();
}
private void he(){
this.name=name;
hello();
this.he();
}
}
用法三:this()
此格式用于构造器内,比如我们可以在无参构造内调用含参构造,那么这时候就需要在this()传入参数来实现,同理要想在含参构造内调用无参构造,只需在构造器代码第一行写this()即可,但是注意,this()与this(参数列表)不可同时使用!
代码实现:
public Student(){
this("name");
this.name=name;
this.he();
}
public Student(String name){
// this();两个this不能一起使用
}
注意:
static void play(){
// this.name=name;静态不能调用非静态
}
super和this的区别
调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。
super()和this()类似,区别是,super()从子类中调用父类的构造方法,this()在同一类内调用其它方法。
super()和this()均需放在构造方法内第一行。
尽管可以用this调用一个构造器,但却不能调用两个。
this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字
面向对象面向对象和面向过程的区别
面向过程,就是遇到一个问题时,将解决问题的方法拆分成一个个函数和数据,然后按一定的顺序执行完。这是一个具体的、流程化的过程。比如洗衣服的流程,先加洗衣粉、再加水、再把衣服扔进洗衣机、洗衣机洗衣、再烘干。
面向对象,就是将解决问题的方法模型化、抽象化成对象。然后给这些对象赋予属性和方法,并让对象来执行这些操作。对于洗衣服的例子,就可以抽象出人和洗衣机两个对象,操作步骤就是人.放洗衣粉()、人.加水()、人.放入洗衣机()、洗衣机.洗衣服()、洗衣机.烘干()。
| 优缺点 | 面向过程 | 面向对象 |
|---|---|---|
| 优点 | 性能更好,因为类调用的时候需要实例化,开销比较大。一些注重性能的程序设计一般采用面向过程开发,比如Linux,单片机 | 易维护、易拓展、易复用,由于面向对象的封装、继承、多态等特性,能设计出低耦合的系统,方便拓展,复用。 |
| 缺点 | 难以维护,难以拓展,难以复用 | 性能比面向过程低 |
封装
面向对象的封装性指的是将对象封装成一个高度自治和相对封闭的个体,对象状态(属性)由这个对象自己的行为(方法)来读取和改变
抽象
抽象就是找出一些事物的相似和共性之处,然后将这些事物归为一个类,这个类只考虑这些事物的相似和共性之处,并且会忽略与当前主题和目标无关的那些方面,将注意力集中在与当前目标有关的方面。就是把现实生活的对象,抽象为类。
继承
在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并可以加入若干新的内容,或修改原来的方法使之更适合特殊的需要,这就是继承。比如,遗产的继承。
多态
多态指的是程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底在哪个类中实现的方法,必须在由程序运营期间才能决定。 比如
其中Java 面向对象编程三大特性:封装 继承 多态封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,将变化隔离,便于使用,提高复用性和安全性。
继承:继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承可以提高代码复用性。继承是多态的前提。
关于继承如下 3 点请记住:
-
子类拥有父类非 private 的属性和方法。
-
子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
-
子类可以用自己的方式实现父类的方法。
-
多态性:父类或接口定义的引用变量可以指向子类或具体实现类的实例对象。提高了程序的拓展性。
在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。
什么是多态机制?Java语言是如何实现多态的?所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。
值传递和引用传递有什么区别?Java中参数是什么传递方式?值传递:传递的参数是值得拷贝。即使在函数中被改动也只是改动的副本。
引用传递:传递的参数是参数的地址,类似C++中的指针,指向参数对应的内存地址。在方法中改动对应地址中的值会影响到任何指向该地址区域的变量。
Java中是值传递,无论是基本数据类型还是对象。
Java实现多态有三个必要条件:继承、重写、向上转型。继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
重载和重写有什么区别?重载:发生在同一个类中,方法名相同但参数列表不同,参数列表包括参数类型,参数个数,参数的顺序。但与方法的返回类型和访问修饰符无关,即重载的方法不能通过返回类型来区分。
重写:发生在父类和子类中,方法名、参数列表必须完全相同。而且返回值的级别应该比父类要小,抛出的异常级别也要比父类小,访问修饰符的级别要高于父类。例如父类返回LIst,子类就可以返回ArrayList;父类抛出Exception,子类就可以抛出IOException;父类的方法是public,子类可以是private。
构造器能被重写吗?构造器不能被继承,因此不能被重写。但可以被重载。
面向对象五大基本原则是什么单一职责原则SRP(Single Responsibility Principle)
类的功能要单一,不能包罗万象,跟杂货铺似的。
开放封闭原则OCP(Open-Close Principle)
一个模块对于拓展是开放的,对于修改是封闭的,想要增加功能热烈欢迎,想要修改,哼,一万个不乐意。
里式替换原则LSP(the Liskov Substitution Principle LSP)
子类可以替换父类出现在父类能够出现的任何地方。比如你能代表你爸去你姥姥家干活。哈哈~~
依赖倒置原则DIP(the Dependency Inversion Principle DIP)
高层次的模块不应该依赖于低层次的模块,他们都应该依赖于抽象。抽象不应该依赖于具体实现,具体实现应该依赖于抽象。就是你出国要说你是中国人,而不能说你是哪个村子的。比如说中国人是抽象的,下面有具体的xx省,xx市,xx县。你要依赖的抽象是中国人,而不是你是xx村的。
接口分离原则ISP(the Interface Segregation Principle ISP)
设计时采用多个与特定客户类有关的接口比采用一个通用的接口要好。就比如一个手机拥有打电话,看视频,玩游戏等功能,把这几个功能拆分成不同的接口,比在一个接口里要好的多。
说说抽象类和接口?
面对对象的设计中,复用的重点是抽象层的复用,抽象类和接口都是抽象层的体现。它们有相同点,比如说都不能被实例化,都可以包含方法声明。但又有许多不同的地方:
- 最大的不同点,就是抽象类中能提供某些方法的实现,而JDK8之前,接口不能提供方法的实现。如果向一个抽象类中添加一个具体实现的方法,那么它所有子类都具有了这个方法,而接口做不到这一点。
- 抽象类需要使用extents关键字继承,但由于Java的单继承特性,使得一个类只能继承一个抽象类,这样就有局限性。而一个类可以实现多个接口,这时接口的优势就体现出来了。
- 抽象类中方法和变量的访问修饰符可以是任意的,public、private都行,但接口中方法和变量的访问修饰符必须是public,而且默认是public。
- 接口中的属性必须是static final,但抽象类中的属性可以是任意的。
不过在JDK8中,新增了接口可以实现默认方法的新特性。在方法前加default关键字,就能在接口中实现该方法,继承该接口的类也默认可以调用这个方法。
一个类实现了多个接口中的重名默认方法,调用时会使用哪个?首先判断本来是否重写了默认方法,如果重写了,就直接调用本类的方法。如果本类没重写,那么判断其父类是否重写了,本类和父类中方法优先级最高。
如果以上无法判断,那么子接口的优先级更高。例如类C继承了接口B,接口B继承了接口A,在接口A和B中都实现了一个重名默认方法,那么,B的优先级更高。
如果继承的多个接口是同级的,比如接口A和接口B没有关系,那么就得在本类中显示声明要调用哪一个接口中的实现。
抽象类能用final修饰吗?不能,抽象类是提供其他类继承的,用final修饰就不能被继承了。
普通类和抽象类有哪些区别?普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。
new关键字,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。一个对象引用可以指向0个或1个对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)
变量与方法 成员变量与局部变量的区别有哪些- 位置:成员变量是在类中,方法外定义的变量。局部变量是在方法中定义的变量。
- 作用域:成员变量可以被整个类中的方法或代码块使用。局部变量只针对特定范围有效。
- 生命周期:成员变量随着对象的创建而创建,随着对象的销毁而销毁。局部变量当方法执行完,或语句结束后,就会被销毁。
- 初始值:成员变量有默认初始值。局部变量没有初始值,需要先赋值再使用。
- 使用原则:就近原则,首先在局部范围找,有就使用;接着在成员位置找。
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?帮助子类做初始化工作。
一个类的构造方法的作用是什么?若一个类没有声明构造方法,改程序能正确执行吗?为什么?主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。
构造方法有哪些特性?名字与类名相同;没有返回值,但不能用void声明构造函数;生成类的对象时自动执行,无需调用。
静态变量和实例变量区别-
静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。
-
实例变量: 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
静态方法和实例方法有何不同?静态方法和实例方法的区别主要体现在两个方面:
在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),而不允许访问实例成员变量和实例方法;实例方法则无此限制
在一个静态方法内调用一个非静态成员为什么是非法的?由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。
什么是方法的返回值?返回值的作用是什么?方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!
Java泛型面试题 Java中的泛型是什么 ? 使用泛型的好处是什么?这是在各种Java泛型面试中,一开场你就会被问到的问题中的一个,主要集中在初级和中级面试中。那些拥有Java1.4或更早版本的开发背景的人都知道,在集合中存储对象并在使用前进行类型转换是多么的不方便。泛型防止了那种情况的发生。它提供了编译期的类型安全,确保你只能把正确类型的对象放入集合中,避免了在运行时出现ClassCastException。
Java的泛型是如何工作的 ? 什么是类型擦除 ?这是一道更好的泛型面试题。泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如List在运行时仅用一个List来表示。这样做的目的,是确保能和Java 5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。根据你对这个泛型问题的回答情况,你会得到一些后续提问,比如为什么泛型是由类型擦除来实现的或者给你展示一些会导致编译器出错的错误泛型代码。请阅读我的Java中泛型是如何工作的来了解更多信息。
什么是泛型中的限定通配符和非限定通配符 ?这是另一个非常流行的Java泛型面试题。限定通配符对类型进行了限制。有两种限定通配符,一种是 extends T> 它通过确保类型必须是T的子类来设定类型的上界,另一种是 super T>它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另一方面>表示了非限定通配符,因为>可以用任意类型来替代。更多信息请参阅我的文章泛型中限定通配符和非限定通配符之间的区别。
List extends T>和List super T>之间有什么区别 ?这和上一个面试题有联系,有时面试官会用这个问题来评估你对泛型的理解,而不是直接问你什么是限定通配符和非限定通配符。这两个List的声明都是限定通配符的例子,List extends T>可以接受任何继承自T的类型的List,而List super T>可以接受任何T的父类构成的List。例如List extends Number>可以接受List或List。在本段出现的连接中可以找到更多信息。
如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?编写泛型方法并不困难,你需要用泛型类型来替代原始类型,比如使用T, E or K,V等被广泛认可的类型占位符。泛型方法的例子请参阅Java集合类框架。最简单的情况下,一个泛型方法可能会像这样:
public V put(K key, V value) {
return cache.put(key, value);
}
Java中如何使用泛型编写带有参数的类?
这是上一道面试题的延伸。面试官可能会要求你用泛型编写一个类型安全的类,而不是编写一个泛型方法。关键仍然是使用泛型类型来代替原始类型,而且要使用JDK中采用的标准占位符。
编写一段泛型程序来实现LRU缓存?对于喜欢Java编程的人来说这相当于是一次练习。给你个提示,LinkedHashMap可以用来实现固定大小的LRU缓存,当LRU缓存已经满了的时候,它会把最老的键值对移出缓存。LinkedHashMap提供了一个称为removeEldestEntry()的方法,该方法会被put()和putAll()调用来删除最老的键值对。当然,如果你已经编写了一个可运行的JUnit测试,你也可以随意编写你自己的实现代码。
Array中可以用泛型吗?这可能是Java泛型面试题中最简单的一个了,当然前提是你要知道Array事实上并不支持泛型,这也是为什么Joshua Bloch在Effective Java一书中建议使用List来代替Array,因为List可以提供编译期的类型安全保证,而Array却不能。
内部类 什么是内部类?将一个类定义在另一个类的内部,这就是内部类。内部类和普通类一样,都是类,都可以定义属性、方法 (包括构造方法,静态方法等等)。通常将内部类分为4种:成员内部类、静态内部类、局部(方法)内部类、匿名内部类。在这四种内部类之中,有的内部类可以定义静态成员,有些内部类就不能定义静态成员,再下面将会一一说明。
内部类的分类有哪些虽然内部类和普通的类一样,都可以继承类,实现接口,而且都可以定义成员(属性,方法),但是它们之间还是有区别的;比如成员内部类就不能定义静态成员(静态变量,静态方法),而静态内部类就可以定义静态成员。
内部类可以分为四种:成员内部类、局部内部类、匿名内部类和静态内部类。
内部类和静态内部类的区别
内部类:
1、内部类中的变量和方法不能声明为静态的。
2、内部类实例化:B是A的内部类,实例化B:A.B b = new A().new B()。
3、内部类可以引用外部类的静态或者非静态属性及方法。
静态内部类:
1、静态内部类属性和方法可以声明为静态的或者非静态的。
2、实例化静态内部类:B是A的静态内部类,A.B b = new A.B()。
3、静态内部类只能引用外部类的静态的属性及方法。
inner classes——内部类
static nested classes——静态嵌套类
其实人家不叫静态内部类,只是叫习惯了,从字面就很容易理解了。
内部类依靠外部类的存在为前提,而静态嵌套类则可以完全独立,明白了这点就很好理解了。
非静态内部类中的变量和方法不能声明为静态的原因
静态类型的属性和方法,在类加载的时候就会存在于内存中。使用某个类的静态属性和方法,那么这个类必须要加载到虚拟机中。但是非静态内部类并不随外部类一起加载,只有在实例化外部类之后才会加载。
我们设想一个场景:在外部类并没有实例化,内部类还没有加载的时候如果调用内部类的静态成员或方法,内部类还没有加载,却试图在内存中创建该内部类的静态成员,就会产生冲突。所以非静态内部类不能有静态成员变量或静态方法。
静态内部类
静态内部类同成员内部类一样,也是定义在类里面的类, 只是在类的前面多了一个static关键字修饰:静态内部类可以被四大权限修饰符修饰。
static class StaticInner {
private String innerStaticMember = "静态内部类静态变量";
private String innerMember = "静态内部类成员变量";
private void visit() {
System.out.println("静态内部类访问外部类静态成员: " + staticMember); // ok
System.out.println("静态内部类调用外部类静态方法: ");
staticMethod();
// 这里编译会报错
System.out.println("静态内部类访问外部类非静态成员: " + member); // 报错
System.out.println("静态内部类访问外部类非静态方法: " ); // 报错
ordinaryMethod();
InnerClassTest innerClassTest = new InnerClassTest();
System.out.println(innerClassTest.member);
innerClassTest.ordinaryMethod();
}
}
静态内部类不能直接访问外部类的成员变量或者成员方法,因为静态内部类,是不需要依赖于外部类的(参考: 静态变量不需要依赖类的对象)
// 请看下面的代码,我们在不依赖外部类实例的条件下,创建了一个静态内部类的对象 InnerClassTest.StaticInner staticInner = new InnerClassTest.StaticInner();静态内部类特点
成员内部类静态内部类使用static修饰,可以定义非静态成员,也可以定义静态成员。
静态内部类中的方法(成员方法、静态方法)只能访问外部类的静态成员,不能访问外部类的非静态成员。
静态内部类可以被4大权限修饰符修饰,被public修饰而任意位置的其他类都可以访问,被private修饰只能被外部类内部访问。
静态内部类内部的静态成员,可以直接使用外部类.静态内部类.静态成员访问。
成员内部类定义在一个类的内部,我们可以认为它是外部类的一个成员变量
它可以无条件访问 : 成员内部类的所有成员属性和方法(包括私有和静态),
如下面的示例:
public class InnerClassTest {
private static String staticMember = "外部类静态变量";
private String member = "外部类成员变量";
private static void staticMethod() {} // 外部类静态方法
private void ordinaryMethod() {} // 外部类普通方法
class Inner {
private String innerStaticMember = "成员内部类静态变量 ";
private String innerMember = "成员内部类成员变量";
private void visit() {
System.out.println("成员内部类访问外部类静态成员: " + staticMember); // ok
System.out.println("成员内部类调用外部类成员变量: " + member);
System.out.println("成员内部类调用外部类静态方法: ");
staticMethod();
System.out.println("成员内部类调用外部类普通方法: ");
ordinaryMethod();
}
}
}
需要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象
即默认情况下访问的是成员内部类的成员。
如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量 外部类.this.成员方法
外部类访问成员内部类:
// 成员内部类是依赖于外部类而存在的,也就是说,如果创建内部类的对象,必须存在一个外部类的对象,如下所示 Inner inner = new InnerClassTest().new Inner();局部内部类
局部内部类是定义在一个方法,或者一个作用域里面的类
它和成员变量最主要的区别是局部内部类的访问权限仅限于方法内或该作用域内
// 定义在方法体内的局部内部类
public class InnerClassTest {
private static String staticMember = "外部类静态变量";
private String member = "外部类成员变量";
private String sameNameMember = "外部类同名变量";
private void ordinaryMethod() {
System.out.println("外部类普通方法");
class LocalInner {
// static String localStaticMember = "局部内部类静态变量"; // 编译报错
String localMember = "局部内部类变量";
void visit() {
System.out.println("局部内部类访问外部类静态成员: " + staticMember);
System.out.println("局部内部类访问外部类成员变量: " + member);
System.out.println("局部内部类静态方法访问本类变量: " + localMember);
}
}
LocalInner localInner = new LocalInner();
localInner.visit();
}
}
局部内部类特点
- 局部内部类不能被权限修饰符修饰。
- 局部内部类只能在方法内部使用。
- 局部内部类不能定义静态成员。
- 局部内部类可以直接访问方法内部的局部变量和方法参数。
- 局部内部类可以访问外部类的静态成员、非静态成员。
匿名内部类就是没有名字的内部类,日常开发中使用的比较多。匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。 它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类.
一个最简单的示例:
public class InnerClassTest {
interface InnerService{
void method();
}
private void test() {
new InnerService() {
@Override
public void method() {
System.out.println("匿名内部类! ");
}
}.method();
}
}
匿名内部类还有以下特点:
匿名内部类包括以下部分:匿名内部类必须继承一个抽象类或者实现一个接口。
匿名内部类不能定义任何静态成员和静态方法。
当所在的方法的形参需要被匿名内部类使用时,必须声明为 final。
匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
- 操作符new
- 一个需要实现的接口或要继承的类, 本例是以实现接口为例,实现了InnerService接口
- 一对括号,如果是匿名子类,与实例化普通类的语法类似,如果有构造参数,要带上构造参数;如果是实现一个接口,只需要一对空括号即可;
- 一段被"{}"括起来类声明主体;
- 末尾的";"号(因为匿名类的声明是一个表达式,是语句的一部分,因此要以分号结尾)。
内部类的优点
- 匿名内部类可以访问外部内的所有成员;
- 匿名内部类不能访问外部类未加final修饰的变量(注意:JDK1.8即使没有用final修饰也可以访问)
- 属性屏蔽,类似于成员内部类,匿名内部类定义的类型(如变量)会屏蔽其作用域范围内的其他同名类型(变量)
内部类有哪些应用场景一个内部类对象可以访问创建它的外部类对象的内容,包括私有数据!
内部类不为同一包的其他类所见,具有很好的封装性;
内部类有效实现了“多重继承”,优化 java 单继承的缺陷。
匿名内部类可以很方便的定义回调。
局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final?一些多算法场合
解决一些非面向对象的语句块。
适当使用内部类,使得代码更加灵活和富有扩展性。
当某个类除了它的外部类,不再被其他的类使用时。
以上例子,为什么要加final呢?是因为生命周期不一致, 局部变量直接存储在栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错。加了final,可以确保局部内部类使用的变量与外层的局部变量区分开,解决了这个问题。
重写与重载 构造器(constructor)是否可被重写(override)构造器不能被继承,因此不能被重写,但可以被重载。
重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
重载:发生在同一个类中方法名相同,但是参数个数不同、参数顺序不同、参数类型不同,返回值类型和访问修饰符可以不同,发生在编译时。
public class Animal {
//父类的eat()方法
public void eat() {
System.out.println("吃东西");
}
}
public class Dog extends Animal {
//Dog重写了父类Animal的eat()方法
@Overwrite
public void eat() {
System.out.println("啃骨头");
}
}
重写:子类继承父类时候,重写父类方法。方法名和参数列表相同,子类重写的权限访问修饰符要大于父类,返回值小于等于父类,抛出异常范围小于等于父类。如果父类是private修饰的,则子类不能重写该方法。
public class Animal {
//父类的eat()方法
public void eat() {
System.out.println("吃东西");
}
}
public class Dog extends Animal {
//Dog重写了父类Animal的eat()方法
@Overwrite
public void eat() {
System.out.println("啃骨头");
}
}
== 和 equals 的区别是什么
一、对象类型不同
1、equals():是超类Object中的方法。
2、==:是操作符。
二、比较的对象不同
1、equals():用来检测两个对象是否相等,即两个对象的内容是否相等。
2、==:用于比较引用和比较基本数据类型时具有不同的功能,具体如下:
(1)、基础数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。
(2)、引用数据类型:比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。
三、运行速度不同
1、equals():没有==运行速度快。
2、:运行速度比equals()快,因为只是比较引用。
equals()和==的源码定义:
public boolean equals(Object obj) {
return (this == obj);
}
由equals的源码可以看出这里定义的equals与==是等效的(Object类中的equals没什么区别),不同的原因就在于有些类(像String、Integer等类)对equals进行了重写。
但是没有对equals进行重写的类就只能从Object类中继承equals方法,其equals方法与==就也是等效的,除非在此类中重写equals。
举个例子:
public class test1 {
public static void main(String[] args) {
String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
if (aa == bb) // true
System.out.println("aa==bb");
if (a == b) // false,非同一对象
System.out.println("a==b");
if (a.equals(b)) // true
System.out.println("aEQb");
if (42 == 42.0) { // true
System.out.println("true");
}
}
}
说明:
String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。
对equals重新需要注意五点:
1、自反性:对任意引用值X,x.equals(x)的返回值一定为true;
2、对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
3、传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true ;
4、 一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变;
5、非空性:任何非空的引用值X,x.equals(null)的返回值一定为false 。
==:
== 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。
1、比较的是操作符两端的操作数是否是同一个对象。
2、两边的操作数必须是同一类型的(可以是父子类之间)才能编译通过。
3、比较的是地址,如果是具体的阿拉伯数字的比较,值相等则为true,如:
int a=10 与 long b=10L 与 double c=10.0都是相同的(为true),因为他们都指向地址为10的堆。
equals:
equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。
String s="abce"是一种非常特殊的形式,和new 有本质的区别。它是java中唯一不需要new 就可以产生对象的途径。
以String s=“abce”;形式赋值在java中叫直接量,它是在常量池中而不是象new一样放在压缩堆中。这种形式的字符串,在JVM内部发生字符串拘留,即当声明这样的一个字符串后,JVM会在常量池中先查找有有没有一个值为"abcd"的对象。
如果有,就会把它赋给当前引用.即原来那个引用和现在这个引用指点向了同一对象,如果没有,则在常量池中新创建一个“abcd"”,下一次如果有Strings1=“abcd”;又会将s1指向“abcd”这个对象,即以这形式声明的字符串,只要值相等,任何多个引用都指向同一对象。
而String s=new String("abcd”);和其它任何对象一样.每调用一次就产生一个对象,只要它们调用。
也可以这么理解:String str="hello”;先在内存中找是不是有“hello”这个对象,如果有,就让str指向那个“hello”。
如果内存里没有"hello",就创建一个新的对象保存"hello”.String str=new String(“hello")就是不管内存里是不是已经有"hello"这个对象,都新建一个对象保存"hello"。
hashCode 与 equals (重要)hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。
散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)
为什么要有 hashCode我们以“HashSet 如何检查重复”为例子来说明为什么要有 hashCode:
当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。
hashCode()与equals()的相关规定对象的相等与指向他们的引用相等,两者有什么不同?如果两个对象相等,则hashcode一定也是相同的
两个对象相等,对两个对象分别调用equals方法都返回true
两个对象有相同的hashcode值,它们也不一定是相等的
因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
对象的相等 比的是内存中存放的内容是否相等而 引用相等 比较的是他们指向的内存地址是否相等。
java只有值传递在C++中,函数传值有两种方式,即值传递和引用传递。而在Java中,只有值传递,即便传递的对象为引用类型(如String)。所谓的值传递是指在调用函数时将实参复制一份传递到函数中,这样函数中操作的是实参的副本,不会对实参造成修改;所谓的引用传递是指在调用函数时将实参的地址传递到函数中,这样函数中操作的是实参对象,函数内部的修改会影响到实参。
枚举类 枚举类中的声明访问修辞符 enum 枚举名 {
枚举成员,
枚举成员,
...
};
Java枚举类的使用规则
IO流 什么是比特(Bit)?什么是字节(Byte)?什么是字符(Char)?以及他们的区别?至于枚举你也有所了解了,Java中的枚举也是一样的。而Java中枚举类的使用,也有特定的规则和场景。如果你看了以下的规则不明白的话,没有关系,继续向下学你就会明白,因为我在下面都会有讲解到这些规则。如下几个规则:
- 类的对象是确定的有限个数。
- 当需要定义一组常量时,建议使用枚举。
- 如果枚举类中只有一个对象,则可以作为单例模式的实现方法。
- 枚举类不能被继承
- 枚举类不能被单独的new创建对象
- 枚举类中的枚举成员是用,隔开的,多个枚举成员之间用_隔开
- 如果枚举类中的只有一个或多个枚举成员,其他什么都没有,我们在用,隔开的同时。最后可以省略;结束符。
Bit 位,是计算机最小的二进制单位 ,取0或1,主要用于计算机操作。
Byte 字节,是数据的最小单位,由8位bit组成,取值(-128-127),主要用于计算机操作数据。
Char 字符,是用户可读写的最小单位,由16位bit(2个byte)组成,取值(0-65535),主要用于用户操数数据。
它是指数据从源头 流到 目的地,所以常把这种数据流叫做IO流。
常用来处理设备之间的数据传输、文件的上传、下载、拷贝。
流分输入和输出,输入流从文件中读取数据存储到进程中,输出流从进程中读取数据然后写入到目标文件。
java 中 IO 流分为几种?按照流的流向分,可以分为输入流和输出流;
按照操作单元划分,可以划分为字节流和字符流;
按照流的角色划分为节点流和处理流。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qSVSCXVk-1653027644127)(/Users/liyang/Desktop/676d7c6163c523aa5f8d4cb7de55d62a.jpeg)]



