1.Java 文件经过 JVM 编译成字节码文件, 即. class 文件, 将字节码文件在不同的操作系统中运行时, 操作系统再将字节码文件编译成机器码文件. 这就是 Java 跨平台
2. 首先明确一点, java 的 GC 回收是完全自动的, 没有提供相关 API 手动回收, 所有的内存分配和回收权限都在 jvm, 在开发人员手里没有绝对的强制垃圾回收的方法, 不过可以这样去做:
对于不再引用的对象, 及时把它的引用赋为 null. obj = null;
如果内存确实很紧张, 调用 System.gc () 方法来建议垃圾回收器开始回收垃圾, 通知 GC 运行, 但是 Java 语言规范并不保证 GC 一定会执行.
3.java 基本类型的默认值和取值范围
整数类型 byte(1 个字节)short(2 个字节)int(4 个字节)long(8 个字节)
字符类型 char(2 个字节)
浮点类型 float(4 个字节)double(8 个字节)
4. 常见字符的 ASCII 码值如下: 空格的 ASCII 码值为 32; 数字 0 到 9 的 ASCII 码值分别为 48 到 57; 大写字母 "A" 到 "Z" 的 ASCII 码值分别为 65 到 90; 小写字母 "a" 到 "z" 的 ASCII 码值分别为 97 到到 122.
5.Java 标识符有如下命名规则:
由 26 个英文字母大小写, 数字: 0-9 符号:_ $ ¥ 组成
标识符应以字母,_ ,$ 开头.
标识符不能是关键字.
6. 抽象类和接口
关于抽象类
JDK 1.8 以前, 抽象类的方法默认访问权限为 protected
JDK 1.8 时, 抽象类的方法默认访问权限变为 default
关于接口
JDK 1.8 以前, 接口中的方法必须是 public 的
JDK 1.8 时, 接口中的方法可以是 public 的, 也可以是 default 的
JDK 1.9 时, 接口中的方法可以是 private 的
7. 装箱和拆箱
基本数据类型转化成包装类是装箱 (如: int --> Integer).
包装类转化成基本数据类型就是拆箱 (如: Integer --> int).
包装类就是引用类型, 基本数据类型就是值类型.
通过 装箱 和 拆箱 操作, 能够在值类型和引用类型中架起一做桥梁. 换言之, 可以轻松的实现值类型与引用类型的互相转换, 装箱和拆箱能够统一考察系统, 任何类型的值最终都可以按照对象进行处理.
8. 序列化和反序列化
Java 在序列化时不会实例化 static 变量和 transient 修饰的变量, 因为 static 代表类的成员, transient 代表对象的临时数据, 被声明这两种类型的数据成员不能被序列化
9.Java 有两种传递方式, 值传递和引用传递. 基本类型和以 string str = "aaa"; 这种方式创建的都是值传递, 对象创建和数组都是引用传递, 所以在函数的判断形参需要特别注意.
10.Java 垃圾回收机制
垃圾回收主要针对的是堆区的回收, 因为栈区的内存是随着线程而释放的. 堆区分为三个区: 年轻代(Young Generation), 年老代(Old Generation), 永久代(Permanent Generation, 也就是方法区).
年轻代: 对象被创建时 (new) 的对象通常被放在 Young(除了一些占据内存比较大的对象), 经过一定的 Minor GC(针对年轻代的内存回收)还活着的对象会被移动到年老代(一些具体的移动细节省略).
年老代: 就是上述年轻代移动过来的和一些比较大的对象. Major GC (FullGC) 是针对年老代的回收.
永久代: 存储的是 final 常量, static 变量, 常量池.
11. 包引用
import java.util.* ;
能访问 java/util 目录下的所有类, 不能访问 java/util 子目录下的所有类
12.Java 的保留字和关键字
goto 和 const 是保留字也是关键字.
Java 关键字列表 (依字母排序 共 50 组):
abstract, assert, boolean, break, byte, case, catch, char, class, const(保留关键字), continue, default, do, double, else, enum, extends, final, finally, float, for, goto(保留关键字), if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while
保留字列表 (依字母排序 共 14 组),Java 保留字是指现有 Java 版本尚未使用, 但以后版本可能会作为关键字使用:
byValue, cast, false, future, generic, inner, operator, outer, REST, true, var, goto (保留关键字) , const (保留关键字) , null
13. 构造函数不能被继承, 构造方法只能被显式或隐式的调用.(有参和无参均是这样)
14. 文件分为文本文件和二进制文件, 计算机只认识二进制, 所以实际上都是二进制的不同解释方式. 文本文件是以不同编码格式显示的字符, 例如 Ascii,Unicode 等, Windows 中文本文件的后缀名有 ".txt",".log", 各种编程语言的源码文件等; 二进制文件就是用文本文档打开是看不懂乱码, 只要能用文本打开的文件都可以算是文本文件, 只是显示的结果不是你想要的, 二进制文件只有用特殊的应用才能读懂的文件, 例如 ".png",".bmp" 等, 计算机中大部分的文件还是二进制文件
15.servlet 是运行在服务器端的小应用程序, 是接收网络服务的请求和产生响应的一种方式.
servlet 的功能: 接受 http 请求, 产生动态 http 响应. web 容器负责将 HTTP 请求转换为 HttpServletRequest 对象
16. 字符流和字节流
stream 结尾都是字节流, reader 和 writer 结尾都是字符流 两者的区别就是读写的时候一个是按字节读写, 一个是按字符. 实际使用通常差不多. 在读写文件需要对内容按行处理, 比如比较特定字符, 处理某一行数据的时候一般会选择字符流. 只是读写文件, 和文件内容无关的, 一般选择字节流.
17.try 只适合处理运行时异常, try+catch 适合处理运行时异常 + 普通异常. 也就是说, 如果你只用 try 去处理普通异常却不加以 catch 处理, 编译是通不过的, 因为编译器硬性规定, 普通异常如果选择捕获, 则必须用 catch 显示声明以便进一步处理. 而运行时异常在编译时没有如此规定, 所以 catch 可以省略, 你加上 catch 编译器也觉得无可厚非.
18. 泛型仅仅是 java 的语法糖, 它不会影响 java 虚拟机生成的汇编代码, 在编译阶段, 虚拟机就会把泛型的类型擦除, 还原成没有泛型的代码, 顶多编译速度稍微慢一些, 执行速度是完全没有什么区别的.
19.Set 不能有重复的元素, 且是无序的, 要有空值也就只能有一个. 因为它不允许重复. L ist 可以有重复元素, 且是有序的, 要有空值也可以有多个, 因为它可重复
20.DBMS 事务的四个特性
原子性: 事务是一组不可分割的操作单元, 这组单元要么同时成功要么同时失败(由 DBMS 的事务管理子系统来实现);
一致性: 事务前后的数据完整性要保持一致(由 DBMS 的完整性子系统执行测试任务);
隔离性: 多个用户的事务之间不要相互影响, 要相互隔离(由 DBMS 的并发控制子系统实现);
持久性: 一个事务一旦提交, 那么它对数据库产生的影响就是永久的不可逆的, 如果后面再回滚或者出异常, 都不会影响已提交的事务(由 DBMS 的恢复管理子系统实现的)
21.Java 中的 volatile 关键字的功能
volatile 是 java 中的一个类型修饰符. 它是被设计用来修饰被不同线程访问和修改的变量. 如果不加入 volatile, 基本上会导致这样的结果: 要么无法编写多线程程序, 要么编译器 失去大量优化的机会.
500 道面试题 + 答案领取
可见性
可见性指的是在一个线程中对该变量的修改会马上由工作内存 (Work Memory) 写回主内存(Main Memory), 所以会马上反应在其它线程的读取操作中. 顺便一提, 工作内存和主内存可以近似理解为实际电脑中的高速缓存和主存, 工作内存是线程独享的, 主存是线程共享的.
禁止指令重排序优化
禁止指令重排序优化. 大家知道我们写的代码(尤其是多线程代码), 由于编译器优化, 在实际执行的时候可能与我们编写的顺序不同. 编译器只保证程序执行结果与源代码相同, 却不保证实际指令的顺序与源代码相同. 这在单线程看起来没什么问题, 然而一旦引入多线程, 这种乱序就可能导致严重问题. volatile 关键字就可以从语义上解决这个问题.
注意, 禁止指令重排优化这条语义直到 jdk1.5 以后才能正确工作. 此前的 JDK 中即使将变量声明为 volatile 也无法完全避免重排序所导致的问题.
22.Java 跟 C 的区别, C 中赋值后会与 0 进行比较, 如果大于 0, 就认为是 true; 而 Java 不会与 0 比较, 整数型就是整型, 布尔型就是布尔型.
23.Math 类中提供了三个与取整有关的方法: ceil,floor,round, 这些方法的作用于它们的英文名称的含义相对应, 例如: ceil 的英文意义是天花板, 该方法就表示向上取整, Math.ceil(11.3)的结果为 12,Math.ceil (-11.6) 的结果为 - 11;floor 的英文是地板, 该方法就表示向下取整, Math.floor (11.6) 的结果是 11,Math.floor (-11.4) 的结果 - 12; 最难掌握的是 round 方法, 他表示 "四舍五入", 算法为 Math.floor (x+0.5), 即将原来的数字加上 0.5 后再向下取整, 所以, Math.round (11.5) 的结果是 12,Math.round (-11.5) 的结果为 - 11.
24. 不可变类 (Immutable Class) 是一旦被实例化就不会改变自身状态 (或值) 的类.
String 就是一种典型的不可变类.(使用字符串自带的函数改变 string 内容都是相当于创建一个新的 string, 即 new String)
不可变类的主要用途是在多线程环境下确保对象的线程安全.
25.java 中接口的修饰符是 public, 接口中的变量是 public static final, 接口中的方法是 public abstract
26. 类中声明的变量有默认初始值(成员变量); 方法中声明的变量没有默认初始值, 必须在定义时初始化, 否则在访问该变量时会出错(局部变量).
27. 方法中不能使用 private 修饰变量(在类中可以)
因为 private 修饰符是使用在类的 , 如果在在类中声明一个成员变量使用 private 修饰后, 这个变量只能被这个类中的方法所访问, 而在方法体中声明变量, 这个变量的作用域是从这个变量声明直到方法体结束, 如果再使用 private 修饰的话两者就会冲突, 所以不能在方法体内声明一个变量为 private, 而且在方法里声明变量为 private 也没什么意义, 方法内声明的变量的作用域本来就在方法体内, 也在他本身的类中, 自然也不会被其他类中的方法所访问
28. 管道
对于管道, 有下面这几种类型:
1普通管道(PIPE): 通常有两种限制, 一是单工, 即只能单向传输; 二是血缘, 即常用于父子进程间(或有血缘关系的进程间).
2流管道(s_pipe): 去除了上述的第一种限制, 实现了双向传输.
3命名管道(name_pipe): 去除了上述的第二种限制, 实现了无血缘关系的不同进程间通信.
要求是对于不同的服务器之间的通信, 是要要求全双工形式的, 而管道只能是半双工, 虽然可以双向, 但是同一时间只能有一个方向传输, 全双工和半双工的区别可以如下图示理解:
29.Vector 类 是在 java 中可以实现自动增长的对象数组
vector 是线程安全的 ArrayList(Vector 和 List 用法差不多, 不过现在已经很少用了, List 已经能全部取代 Vector 了), 在内存中占用连续的空间. 初始时有一个初始大小, 当数据条数大于这个初始大小后会重写分配一个更大的连续空间. 如果 Vector 定义为保存 Object 则可以存放任意类型.
30. 关于多线程中的 start 方法和 run 方法的区别
启动多线程有两种方式, 但是无论是依靠那种方式, 最终都是需要调用 thread 的 start 方法, 而决定了线程去做什么, 则需要重写 run 方法, 假如, 我们重写了 run 方法, 同时在 main 线程中 new 了一个 thread, 第一种情况, 调用该 thread 的 start 方法, 这时就产生了一个新的线程, 这个线程处于就绪状态, 等待 CPU 调度; 第二种情况, 调用了该 thread 的 run 方法, 这时就不会产生新的线程, 依旧在 main 线程中执行.
来源: http://www.jianshu.com/p/be7d5363442c