JavaSE学习笔记01-Java基础知识
Java特性与优势
- 简单性
- 面向对象
- 可移植性
- 高性能(即时编译)
- 分布式
- 动态性(反射)
- 多线程
- 安全性(异常机制等)
- 健壮性
Java三大版本
- JavaSE:标准版 (桌面程序,控制台开发……)
- JavaME:嵌入式开发(基本上废弃)
- JavaEE:企业级开发(Web端,服务器开发)
JDK vs JRE vs JVM
此部分摘录来自 JavaGuide
JVM
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。
为什么说 Java 语言“编译与解释并存”?
高级编程语言按照程序的执行方式分为编译型和解释型两种。简单来说,编译型语言是指编译器针对特定的操作系统将源代码一次性翻译成可被该平台执行的机器码;解释型语言是指解释器对源程序逐行解释成特定平台的机器码并立即执行。比如,你想阅读一本英文名著,你可以找一个英文翻译人员帮助你阅读,
有两种选择方式,你可以先等翻译人员将全本的英文名著(也就是源码)都翻译成汉语,再去阅读,也可以让翻译人员翻译一段,你在旁边阅读一段,慢慢把书读完。
Java 语言既具有编译型语言的特征,也具有解释型语言的特征,因为 Java 程序要经过先编译,后解释两个步骤,由 Java 编写的程序需要先经过编译步骤,生成字节码(*.class 文件),这种字节码必须由 Java 解释器来解释执行。因此,我们可以认为 Java 语言编译与解释并存。
Oracle JDK 和 OpenJDK 的对比
可能在看这个问题之前很多人和我一样并没有接触和使用过 OpenJDK 。那么 Oracle JDK 和 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 的所有部分,除了我们考虑商业功能的部分。
Java开发环境搭建
卸载JDK
- 删除Java的安装目录
- 删除JAVA_HOME
- 删除PATH下关于Java的目录值
- CMD执行java -version
JDK下载与安装
-
选择需要的Java Window版本下载
-
解压程序包到合适的位置安装
-
配置JAVA环境变量,添加JAVA_HOME变量与PATH变量,注意PATH需要配置java下的bin目录和Jre下的bin目录
-
CMD执行java -version
JDK主要目录文件说明
- bin - 可执行程序存放目录
- include - 头文件的存放目录
- jre - JRE相关可执行程序的存放目录
- lib - Java的类库
- src.zip - Java基础类库源代码
HelloWorld 及简单语法规则
- 创建 HelloWorld.java 文件,输入如下内容
public class HelloWorld{
public static void main(String[] args) {
System.out.print("Hello,World!");
}
}
- 在文件目录的路径中输入cmd回车打开CMD,执行 javac HelloWorld.java 编译为字节码文件
- 运行程序,CMD 执行 java HelloWorld
Java程序运行机制
编译型
解释型
程序运行机制
源程序 --> Java编译器 --> 字节码 --> 类加载器 --> 字节码校验器 --> 解释器 --> 操作系统平台
Java同时具备编译型和解释型程序的特征
使用IDE开发-IDEA
-
IDEA安装
-
使用技巧
psvm + TAB 快速生成main方法
sout + TAB 快速生成 System.out.println('')
-
IDEA优化
基础知识
注释、标识符、关键字
注释
- 注释不会被执行,是给程序员看的
- 分类:单行注释、多行注释、文档注释
标识符
- 标识符就是一个名字,比如类的名字,变量的名字等等
- 标识符只能以字母(A-Z或者a-z),美元符($)、或下划线开头
- 首字母后可以是字母(A-Z或者a-z),美元符($)、下划线或数字的任意字符组合
- 标识符是大小写敏感的
- 不能使用关键字作为变量名或方法名
- 可以使用中文命名,但不建议
关键字
- Java自带的标识符
数据类型
-
强类型语言:要求变量的使用严格符合规定,所有变量都必须先定义才能使用
-
弱类型语言:对变量的没有严格的规定
-
Java是强类型语言
-
Java的数据类型分两大类
-
基本类型
类型分类 类型 大小 整数类型 byte 1 字节 整数类型 short 2 字节 整数类型 int 4 字节 整数类型 long 8 字节 浮点类型 float 4 字节 浮点类型 double 8 字节 字符类型 char 2 字节 布尔类型 boolean 1 比特位 -
引用类型(除以上八大基本数据类型之外的类型)
-
代码示例
public class Demo02 { public static void main(String[] args) { // 八大基础数据类型 //整数 int num1 = 1000; byte num2 = 123; short num3 = 30; long num4 = 1L; //小数:浮点数 float num5 = 50.1F; double num6 = 3.111; //字符 char name = '国'; // 字符串, String不是关键字,是类 //String name = "中国"; //布尔值 boolean flag = true; //boolean flag = false; // 引用类型,除以上八大基本数据类型之外的类型 } } -
类型转换
-
由于Java是强类型语言,所以要进行有些运算时,需要用到类型转换
-
运算中,不同类型的数据先转换成同一类型,然后运算(决定转换成哪一类型由下面的优先级确定,范围低转高,整数转小数)
byte,short,char -> int -> long -> float -> double -
强制类型转换
int i = 128; //强制类型转换 (类型) 变量名 高转换到低 //自动类型转换 低到高 byte b = (byte) i; // 内存溢出 System.out.println(i);// 128 System.out.println(b);// -128 -
自动类型转换
变量、常量、作用域
变量
-
变量:右值会变化的量
-
Java是一种强类型语言,每个变量都必须声明其类型
-
Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
type varName [=value] [{,varName[=value]}]; //数据类型 变量名 = 值;可以使用逗号隔开来声明多个同类型变量 -
注意事项
- 每个变量都有类型,类型可以是基本类型,也可以是引用类型
- 变量名必须是合法的标识符
- 变量声明是一条完整的语句,因此每个声明语句需要分号结尾
-
变量作用域
- 类变量
- 实例变量
- 局部变量
public class Demo05 { //类变量 static ,从属于整个类 static double salary = 2500; //属性:变量 //实例变量: 从属于对象,如果不自行初始化,变量存在默认值 //布尔值的默认值: false //基本数据类型数值类型:0, 0.0 //其余的默认值均为 null String name; int age; //main方法 public static void main(String[] args) { //局部变量:必须声明和初始化值,只在当前{}内有效 int i = 10; System.out.println(i); //实例变量的使用 Demo05 demo05 = new Demo05(); System.out.println(demo05.name); System.out.println(demo05.age); //调用类变量 System.out.println(salary); } //其他方法 public void add(){ System.out.println(salary); } }
常量
- 常量(Constant):初始化后不能再改变的值!不会变动的值。
- 所谓常量可以理解为一种特殊的值,它的值被设定后,在程序运行过程中不允许被改变。
final 常量名 = 值;
final double PI = 3.14;
- 常量名一般使用大写字符。
变量的命名规范
- 所有的变量、方法、类名:需要做到见名知意
- 类成员变量:遵守首字母小写和驼峰原则,比如 monthSalary
- 局部变量:遵守首字母小写和驼峰原则
- 常量:仅使用大写字母和下划线,比如 MAX_VALUE
- 类名:遵守首字母大写和驼峰原则,比如 Man,GoodMan
- 方法名:遵守首字母小写和驼峰原则,比如 run(),runRun()
运算符
运算符说明
- 概览

- 自增 自减运算符说明
public class Demo04 {
public static void main(String[] args) {
// 一元运算符:++ -- 自增 自减
int a = 3;
int b = a++; // b = 3 a = 4 ++在后,先自增后赋值
int c = ++a; // c = 5 a= 5 ++在前,先赋值后自增
System.out.println(a); // 5
System.out.println(b); // 3
System.out.println(c); // 5
//幂运算 3^2 使用工具类操作
double pow = Math.pow(3, 2);
System.out.println(pow);
}
}
- 逻辑运算符
public class Demo05 {
public static void main(String[] args) {
// 逻辑运算符
// 与(and) 或(or) 非(取反)
boolean a = true;
boolean b = false;
System.out.println("a && b: " + (a&&b)); //逻辑与
System.out.println("a || b: " + (a||b)); //逻辑或
System.out.println("! (a && b): " + !(a&&b)); //逻辑非
}
}
- 逻辑运算的短路现象
public class Demo05 {
public static void main(String[] args) {
// 短路现象
int c = 5;
boolean d = (c < 4) && (c++ < 4); // && 逻辑与运算需要全为真,当第一个为false时,可以确定整个返回为false,不会继续往下执行判断,直接返回false
System.out.println(d);
System.out.println(c);
}
}
- 三元运算符
public class Demo08 {
public static void main(String[] args) {
// x ? y : z
// 如果 x==true ,则结果为y,否则为z
int score = 80;
String type = score < 60 ? "不及格" : "及格"; //必须掌握
System.out.println(type);
}
}
运算符优先级
所有的数学运算都认为是从左向右运算的 ,Java语言中大部分运算符也是从左向右结合的,只有单目运算符、赋值运算符和三目运算符例外,其中,单目运算符、赋值运算符和三目运算符是从右向左结合的,也就是从右向左运算。
乘法和加法是两个可结合的运算,也就是说,这两个运算符左右两边的操作数可以互换位置而不会影响结果。运算符有不同的优先级,所谓优先级就是在表达式运算中的运算顺序。
一般而言,单目运算符优先级较高,赋值运算符优先级较低。算术运算符优先级较高,关系和逻辑运算符优先级较低。多数运算符具有左结合性,单目运算符、三目运算符、赋值运算符具有右结合性。
Java 语言中运算符的优先级共分为 14 级,其中 1 级最高,14 级最低。在同一个表达式中运算符优先级高的先执行。表 1 列出了所有的运算符的优先级以及结合性。
| 优先级 | 运算符 | 结合性 |
|---|---|---|
| 1 | ()、[]、{} | 从左到右 |
| 2 | !、+、-、~、++、-- | 从右到左 |
| 3 | *、/、% | 从左到右 |
| 4 | +、- | 从左到右 |
| 5 | «、»、>>> | 从左到右 |
| 6 | <、<=、>、>=、instanceof | 从左到右 |
| 7 | ==、!= | 从左到右 |
| 8 | & | 从左到右 |
| 9 | ^ | 从左到右 |
| 10 | | | 从左到右 |
| 11 | && | 从左到右 |
| 12 | || | 从左到右 |
| 13 | ?: | 从右到左 |
| 14 | =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= | 从右到左 |
包机制
- 为了更好的组织类,Java提供了包机制,用于区别类名的命名空间。
- 包语句的语法格式为:
package pkg1[. pkg2[. pkg3...]];
- 一般使用公司域名倒置作为包名
- 为了能够使用某一个包的成员,我们需要在Java程序中明确导入改包,使用‘’import‘语句可完成此功能
import package1[.package2...].(classname|*);
JavaDoc
- javadoc 命令是用来生成自己的API文档的
- 参数信息
- @author 作者名
- @version 版本号
- @since 指明需要使用的jdk版本
- @param 参数名
- @return 返回值情况
- @throws 异常抛出情况
- 使用IDEA生成JavaDoc: https://www.jianshu.com/p/cf085c04cceb

浙公网安备 33010602011771号