共计 10017 个字符,预计需要花费 26 分钟才能阅读完成。
一、Java
Java 诞生于 1995 年,原属于 SUN 公司,2009 年 4 月 20 日,美国数据软件巨头甲骨文公司(Oracle)发表以 74 亿美元收买 SUN 公司。Java 是最受欢迎的开发语言,曾经火了 20 年,并将持续引领着 IT 的编程语言。Java 的 LOGO 是一杯热气腾腾的咖啡,真的是令人回味无穷
1.1 为什么 Java 是平台无关性(能够跨平台)
传统语言
Java 语言
咱们能够对 Java 程序进行编译操作,编译后生成一种和平台零碎无关的文件——字节码文件 (.class)。然而此时 Windows、Linux 均不能执行字节码文件, 只有 Java 虚拟机(JVM) 能够辨认字节码文件, 那么为了在 Windows 零碎上运行该 Java 程序,咱们就只能在 Windows 平台上装置 Windows 版本的 JVM,如果要在 Mac 零碎上运行,那么得装置 Mac 版本的 JVM, 总结来说就两点:
- Java 编译后生成和平台无关的.class 文件
- jvm 是平台相干的
在这里进行编译操作的工具叫做 javac,启动 JVM 并把字节码加载进 JVM 的工具叫做 java
二、Java 环境
2.1、JRE
JRE(Java Runtime Environment):Java 运行环境,如果要运行 Java 程序,就须要 JRE 的反对,JRE 里蕴含 JVM,个别在只运行程序而不开发程序的服务器中装置
2.2、JDK
JDK(Java Development Kit):Java 开发工具,蕴含开发 Java 程序的所有工具如 javac 和 java 等,JDK 蕴含 JRE,如果曾经装置了 JDK 就不用装置 JRE
2.3、JVM
JVM(Java Virtual Machine):Java 虚拟机,它是运行所有 Java 程序的虚构计算机。JVM 是不跨平台的,在 Windows 下装 Windows 版的 JVM,在 Linux 下装 Linux 版的 JVM
三、Java 编译和运行的机制
- 编写源文件(Java 文件)
- 应用 Java c 工具对源文件进行编译操作(java c 源文件.java), 生成.class 文件
- 生成字节码文件 (.class 文件) 之后, 应用 Java 工具启动 JVM, 运行程序(java 主办法的类名)
四、Java 根底
4.1、语法规定
- Java 语言严格辨别大小写,大写和小写是不同的概念
- 一个 Java 源文件里能够定义多个 Java 类, 但其中最多只能有一个类被定义为 public 类, 但如果源文件中蕴含了 public 类, 源文件必须和 public 类同名
- 一个源文件中蕴含了 N 个 Java 类时, 胜利编译后会生成 N 份字节码文件, 每一个类都会生成独自的.class 文件, 且字节码的文件名和其对应的类名雷同
- 若一个类想要运行, 则必须领有主办法(main), 因为 main 办法是程序的入口
4.2、正文
Java 提供 3 种正文类型:
- 单行正文
// 这是单行正文
// 快捷键:Ctrl+/
- 多行正文
/*
我是多行正文
快捷键为: 打 /* 再按回车
*/
- 文档正文
/*
*
* 我是文档类型
* 快捷键为: 打 /* 而后按几下 tab 键
*/
多行正文之间彼此都不能穿插嵌套, 因为 /
会找举例本人最近的 /
符号,组成一个正文语句块,上图中独自的 */
符号就不能被编译器辨认了
4.3、关键字和保留字
关键字
关键字:在编程语言中当时定义的,有着非凡含意和用处的单词
保留字
保留字:和关键字一样是编程语言当时定义好的,只是说当初临时没有非凡的性能,但说不定当前某天会忽然被赋予性能,因而被保留下来的单词。比方 goto 和 const 就是保留字
4.4、分隔符和标识符
4.4.1、分隔符
- 分号(;):语句的宰割,示意一句话完结,好比咱们应用的句号。
- 花括号({}):示意一个代码块,是一个整体,花括号要成对应用。
- 方括号([]):定义数组和拜访数组元素时应用。
- 圆括号(()):应用很宽泛,具体用到细讲。
- 圆点(.):类和对象拜访它的成员时应用。
- 空格():把一整条语句宰割成几段,空格的次数不限度,好比一句英文里单词都要离开写一样。
4.4.2、标识符
在写代码的时候为了加强代码的浏览性,咱们会自定义很多名字如:类名、办法名、变量名等。在编程的里,咱们把这种为了加强程序浏览性而自定义的名称,称为标识符
标识符的命名规定:
- 由字母、数字、下划线、$ 组成,但不能以数字结尾(注:此处的字母能够是中文、日文等)
- 大小写敏感
- 不能应用 Java 中的关键字和保留字
- 不能用 Java 中内置的类名
4.5、数据类型
留神:Java 只有 8 大数据类型,String 不属于根本数据类型, 他属于援用数据类型
罕用的整数类型是 int 和 long,byte 和 short 根本不必,罕用的小数类型是 double,float 根本不必。因为 double 是不准确的,在理论开发中示意准确的小数咱们应用 BigDecimal 类
- 整数类型默认是 int 类型,小数类型默认是 double 类型
- 示意 long 类型常量,要加 L 或者 l,倡议加 L
- 示意 float 类型常量,要加 F 或者 f,倡议加 F
五、变量
变量是 内存中一块区域,能够往该区域存储数据,批改外面的数据,也能够获取外面的数据,一个变量如果没有被初始化,就意味着没有分配内存空间来存储,就不能应用
定义变量的语法格局如下:
- String,示意类型,这里能够写任何的类型
- name:变量名,和咱们的姓名一样了解,没有为什么
- =:赋值运算符,前面会讲,意思是将左边的值赋值给右边的变量
- “xiaolin”:一个字符串类型的值,如果是其余类型,不要加引号
变量的几个特点:
- 占据着内存中某一块存储区域
- 该区域有本人的变量名和数据类型
- 能够被重复使用
- 该区域的变量值能够在 同一个类型的范畴内 一直地变动
5.1、变量的定义以及赋值
public class VarDemo{public static void main(String[] args) {
// 形式一,先定义变量,再赋值
// 数据类型 变量名; 如:int age;// 变量名 = 常量值;
// 定义一个 int 类型变量, 初始值为 17
int name;
// 批改 age 变量的值为 17
age = xiaolin;
System.out.println(age);
// 形式二,在申明时同时赋值(举荐)// 数据类型 变量名 = 初始化值;
// 定义一个 String 类型的变量,初始值为 zs
String name = "zs";
}
}
变量的应用留神如下几点:
- 变量必须是先申明再应用,并且初始化后才能够应用(定义包装类除外)
- 定义变量必须有数据类型
- 变量从开始定义到所在的作用域内能够应用,出了作用域之外就不能够应用了,且在同一作用域内,变量名不能够反复
常见的几种变量类型的定义:
public class VarDemo{public static void main(String[] args) {
//byte 类型变量
byte b = 20;
System.out.println(b);
//short 类型变量
short s = 20;
System.out.println(s);
//int 类型变量
int i = 20;
System.out.println(i);
//long 类型变量, 应用 L 后缀
long l = 20L;
System.out.println(l);
//float 类型变量, 应用 F 后缀
float f = 3.14F;
System.out.println(f);
//double 类型变量
double d = 3.14;
System.out.println(d);
//char 类型变量
char c = 'A';
System.out.println(c);
//boolean 类型变量
boolean bb = true;
System.out.println(bb);
//String 类型变量
String str = "你好";
System.out.println(str);
}
}
5.2、替换两个变量值
思路
- 把 num1 的值存储到长期变量 temp 中去
- 把 num2 的值赋给 num1 变量
- 把 temp 存储的值赋给 num2 变量
实现代码
public class ChangVarDemo{public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
System.out.println("num1=" + num1);
System.out.println("num2=" + num2);
//--------------------------------
// 交互操作
int temp = num1;
num1 = num2;
num2 = temp;
//--------------------------------
System.out.println("num1=" + num1);
System.out.println("num2=" + num2);
}
}
六、表达式
表达式(expression),是由数字、运算符、括号、常量、变量等以能求得后果的组合
七、数据类型的转换
在 8 大根本数据类型中,boolean 不属于数值类型,所以不参加转换,其余类型的转换规则如下图。个别的,byte、short、char 三种类型相互之间个别不参加转换操作,依照转换形式,有两种(留神:boolean 类型不参加类型转换):
- 主动类型转换:范畴小的数据类型间接转换成范畴大的数据类型,小 -> 大
- 强制类型转换:范畴大的数据类型强制转换成范畴小的数据类型,大 -> 小
7.1、主动类型转换与晋升
7.1.1、主动类型转换
主动类型转换,也称为“隐式类型转换,就是把范畴小的数据类型间接转换成范畴大的数据类型
转换规则:byte、short、char—>int—>long—>float—>double
注意事项:byte、short、char 相互之间不转换,他们参加运算首先转换为 int 类型
语法格局:范畴大的数据类型 变量 = 范畴小的数据类型值
public class TypeConvertDemo1{public static void main(String[] args) {
// 把 int 类型变量转为 long 类型
long longNumber = 17;// 整数默认为 int 类型
// 把 long 类型转换为 float 类型
float f1 = longNumber;
// 把 float 类型转换为 double 类型
double d = f1;
// 定义两个 int 类型的变量
int a1 = 2;
int b1 = 3;
int c1 = a1 + b1;
// 定义一个 byte 类型, 一个 int 类型
byte b2 = 2;
int c2 = 3;
System.out.println(b2 + c2);
//byte、short、char 类型参加运算时把本人晋升为 int 类型
//byte d1 = b2 + c2;// 编译报错
int d3 = b2 + c2;// 编译通过
}
}
7.1.2、主动类型晋升
当一个算术表达式中,蕴含多个根本数据类型的常量或变量(boolean 除外)时,整个算术表达式的后果类型将呈现主动晋升,其规定是:
- 所有的 byte、short、char 类型被主动晋升到 int 类型,再参加运算
- 整个表达式的最终后果类型,被晋升到表达式中类型最高的类型
System.out.println('a' + 1);//98
byte b = 22;
b = b + 11;// 编译出错,此时后果类型应该是 int
double d1 = 123 + 1.1F + 3.14 + 99L ;
论断:算数表达式后果的类型就是其中范畴最大的数据类型。
7.2、强制类型转换
强制类型转换,也称为“显式类型转换”,就是把范畴大的数据类型强制转换成范畴小的数据类型
# 语法格局:# 范畴小的数据类型 变量 =(范畴小的数据类型)范畴大的数据类型值;
留神:个别状况下不倡议应用强转,因为强转有可能损失精度
public class TypeConvertDemo2{public static void main(String[] args) {
int a = 2;
byte b = 3;
// 主动类型转换
int c = a + b;
// 强制类型转换
byte d = (byte) (a + b);
// 把 double 转换为 int 类型
int i = (int)3.14;
System.out.println(i);//3
}
}
八、运算符
对常量和变量进行操作的符号称为运算符
常见的运算符分为:算术运算符、赋值运算符、比拟运算符、逻辑运算符、三元运算符
8.1、算数运算符
运算符 | 运算规定 1 | 示例 | 后果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
+ | 加 | 52+3 | 5 |
+ | 拼接字符串 | “ 中 ”+” 国 ” | “中国” |
– | 符号 | int a = 3 -a |
-3 |
– | 减 | 3-1 | 2 |
* | 乘 | 2*3 | 6 |
/ | 除 | 5/2 | 2 |
% | 取模 | 5%2 | 1 |
++ | 自增 | int a = 1<br/>a++(++a) | 2 |
— | 自减 | int b =2 <br/>b–(–b) | 1 |
8.2、自增和自减
自增:++,递增操作符,使变量值减少 1,有前置和后置之分,只能操作变量。
自减:–,递加操作符,使变量值减去 1,有前置和后置之分,只能操作变量。
以 ++ 为例:
a++ 和 ++ a 后果都是让 a 的值自增 1,如果只是须要自增的话,应用哪一种都能够
然而他们俩有惟一的区别:
- 前置(++a): 示意对 a 加 1 之后的后果进行运算,先加后用
- 后置(a++):示意对 a 变量加 1 之前的值(原始值)进行运算,先用后加
public class ArithmeticOperatorsDemo2{public static void main(String[] args) {
int a1 = 5;
int b1 = ++ a1;
System.out.println("a1=" + a1 + ",b1=" + b1);//a1=6,b1=6
int a2 = 5;
int b2 = a2 ++;
System.out.println("a2=" + a2 + ",b2=" + b2);//a2=6,b2=5
}
}
比拟底层的解释
++ a 示意取 a 的地址,减少它的内容,而后把值放在寄存器中
a++ 示意取 a 的地址,把它的值装入寄存器,而后减少内存中的 a 的值
8.3、赋值运算符
运算符 | 运算规定 | 示例 | 后果 |
---|---|---|---|
== | 是否相等于 | 4==3 | false |
!= | 是否不等于 | !4=3 | true |
< | 小于 | 4<3 | false |
> | 大于 | 4>3 | true |
<= | 小于等于 | 4<=3 | false |
>= | 大于等于 | 4>=3 | true |
8.4、三元运算符
三元运算符,示意有三个元素参加的表达式,所以又称为三目运算符,其语义示意 if-else(如果什么状况就做什么,否则做什么)
语法格局:数据类型 变量 = boolean 表达式 ? 后果 A:后果 B
表白的意思,boolean 表达式后果:
- 为 true,则三元运算符的后果是后果 A
- 为 false,则三元运算符的后果是后果 B
留神:
- 三元运算符必须定义变量承受运算的后果,否则报错
- 三元运算符后果的类型由后果 A 和后果 B 来决定的,后果 A 和后果 B 的类型是雷同的
8.5、逻辑运算符
逻辑运算符用于连贯两个 boolean 表达式,后果也是 boolean 类型的
运算符 | 运算规定 | 示范 | 后果 | ||||
---|---|---|---|---|---|---|---|
& | 与 | false & true | false | ||||
\ | 或 | false \ | true | true | |||
^ | 异或 | true ^ false | true | ||||
! | 非 | !true | false | ||||
&& | 短路与 | false && false | false | ||||
\ | \ | 短路或 | false \ | \ | false | true |
法则:
- 非:取反,!true 则 false,!false 则 true
- 与:有 false 则 false
- 或:有 true 则 true
- 异或:^ 雷同则 false, 不同则 true
8.5.1、& 和 &&(| 和 | |)的区别
&:& 右边表达式无论虚实,& 左边表达式都进行运算
&&:如果 && 右边表达式为真,&& 左边表达式参加运算,否则 && 左边表达式不参加运算,故称短路与
| 和 || 的区别同理,||,右边为真,左边不参加运算
public class LogicalOperatorDemo2 {public static void main(String[] args) {System.out.println(false & 1 / 0 == 1);// 报错,阐明左边执行了
System.out.println(false && 1 / 0 == 1);// 不报错,阐明左边没有执行
System.out.println(true | 1 / 0 == 1);// 报错,阐明左边执行了
System.out.println(true | 1 / 0 == 1);// 不报错,阐明左边没有执行
}
}
九、数组
9.1、JVM 初探索
- 程序计数器:以后线程所执行的字节码的行号的指示器
- 本地办法栈:为虚拟机应用的 native 办法服务
- 办法区:线程共享的内存区域,存储曾经被虚拟机加载的类的信息、常量、动态变量,这个区域的内存回收的指标次要是针对常量池的回收和对类型的卸载
- Java 虚拟机栈:简称栈,每个办法被执行的同时会创立一个栈帧用于存储该办法的局部变量、操作栈、动静链接、办法进口等信息
- Java 堆 :被所有线程共享的一块内存区域,在虚拟机创立的时候启动,
所有对象的实例(new 进去的对象)
以及数组
都要在堆上分配内存空间,所以堆占的内存空间远比栈大
- 每当调用一个办法时,创立一个栈帧,寄存了以后办法的局部变量,当办法调用结束时,该办法的栈帧就被销毁了
- 每次 new 一个对象的时候,就示意在内存中开拓了一块新的存储空间
9.2、数组
9.2.1、什么是数组
具备 雷同类型 的多个常量值有序 组织起来的一种数据模式,数组中应用索引来示意元素寄存的地位,索引从 0 开始 , 步长是 1 ,有点像 Excel 表格的行号
9.2.2、定义语法
数组元素类型[] 数组名;
int [] nums;
留神:
- 能够把 int[] 看成一种数据类型,int 类型的数组类型
- int[]数组示意,这个数组中的元素都是 int 类型的,同理
9.2.3、数组的初始化
数组在定义后,必须初始化能力应用。所谓初始化,就是在堆内存中给数组调配存储空间,并为每一个
元素赋上初始值,有两种形式:动态初始化和动静初始化 , 数组的长度是固定的,无论以哪种,一旦初始化实现,数组的长度(元素的个数)就固定了,不能扭转,除非从新对该初始化,初始化时,如果咱们明确了具体的元素就用动态初始化,如果还不晓得具体放哪些元素,只晓得个数,用动静初始化
9.2.3.1、动态初始化
咱们间接为每一个数组元素设置初始化值,而数组的长度由零碎 (JVM) 决定
语法:数组元素类型[] 数组名 = new 数组元素类型[]{元素 1, 元素 2, 元素 3,…….};
int[] nums = new int[]{1,3,5,7,9};
// 简略写法:
int[] nums = {1,3,5,7,9};// 简略写法, 定义和初始化必须同时写进去
9.2.3.2、动态初始化内存剖析
public class ArrayDemo1{public static void main(String[] args) {
// 定义并初始化数组
int[] nums = new int[] {1, 3, 5, 7};
System.out.println("数组长度 =" + nums.length);
// 从新初始化数组
nums = new int[] { 2, 4, 8};
System.out.println("数组长度 =" + nums.length);
}
}
若 num = null,则 null 示意不再援用堆中的内存空间,那么此时 nums 就好比是没有初始化的,不能应用
9.2.3.4、动静初始化
程序员只设置数组元素个数,而数组的元素的初始值由零碎 (JVM) 决定
语法:数组元素类型[] 数组名 = new 数组元素类型[length];
int[] nums = new int[5];
留神:不能同时指定元素值和数组长度,int[] nums = new int[5]{1,3,5,7,9}
是谬误的
内存图与动态初始化一样,只是领有默认值
9.2.4、数组中对元素的操作
9.2.4.1、获取元素的个数
int size = 数组名.length;
9.2.4.2、设置元素
nums[1] = 30;
9.2.4.3、获取元素
元素类型 变量名 = 数组名[index];
9.2.5、数组中常见的异样
- NullPointerException:空指针异样(空援用异样)
操作了一个尚未初始化或者没有分配内存空间的数组
- ArrayIndexOutOfBoundsException:数组的索引越界异样
操作的数组的索引不在 [0,数组名.length-1] 范畴内
9.2.6、数组遍历
9.2.6.1、for 循环
int[] nums = new int[] {1, 3, 5, 7};
for (int index = 0; index < nums.length; index++) {int ele = nums[index];//index 顺次是 0、1、2、3
System.out.println(ele);
}
9.2.6.2、for-each(加强 for 循环)
for(数组元素类型 变量:数组){//TODO}
int[] nums = new int[] {1, 3, 5, 7};
for (int ele : nums) {System.out.println(ele);
}
应用 for-each 操作数组更简略,因为 能够不关怀索引,其底层原理仍然是上述的 for 循环操作数组
9.2.7、二维数组
在之前,数组的每一个元素就是一个个的值,这种数组咱们称之为一维数组。二维数组,就是数组中的每一个元素是另一个一维数组
9.2.7.1、二维数组的定义和初始化
动态
public class ArrayInArrayDemo1 {public static void main(String[] args) {
// 定义三个一维数组
int[] arr1 = { 1, 2, 3};
int[] arr2 = { 4, 5};
int[] arr3 = { 6};
// 把三个一维数组存储到另一个数组中, 那么该数组就是二维数组
int[][] arr = new int[][] {arr1, arr2, arr3};
}
}
二维数组中的元素类型是一维数组,把数组元素类型 [] 看成一个整体,示意数据类型
动静
数组元素类型[][] 数组名 = new 数组元素类型[x][y];x 示意二维数组中有几个一维数组
y 示意每一个一维数组中有几个元素。int[][] arr = new int[3][5];
9.2.7.2、获取二维数组的元素
for 循环
for (int index = 0; index < arr.length; index++) {
// 取出每一个一维数组
int[] arr2= arr[index];
// 迭代一维数组
for (int j = 0; j < arr2.length; j++) {int ele = arr2[j];
System.out.println(ele);
}
System.out.println("-----");
}
for-each
for (int[] arr2 : arr) {
//arr2 为每次遍历进去的一维数组
for (int ele : arr2) {
//ele 为从 arr2 一维数组中遍历进去的元素
System.out.println(ele);
}
System.out.println("-----");
}
十、办法
10.1、办法的定义
办法:为了实现某一特定性能(如:求和,统计数量等)的 代码块
语法格局:
修饰符] 返回值类型 办法名称(参数类型 参数名 1, 参数类型 参数名 2,…)
{
办法体;
[return 返回值;]
}
格局剖析:
- 修饰符:public、static 等,static 润饰的办法间接应用类名调用即可,用 static 润饰的办法都属于类的
-
返回值类型:限定返回值的类型,办法在实现一个性能后,是否须要给调用者返回一个后果?
- 如果须要给调用者返回后果,就写上返回数据的类型
- 如果不须要给调用者返回后果,就用关键字
void
,示意没有返回后果
- 办法名称:用于调用办法,遵循标识符标准,首字母小写,采纳驼峰命名法,见名知意
- 形式参数:办法中圆括号中的变量,能够有多个形式参数
- 办法体:编写如何实现该性能的代码
-
return 关键字的作用
- 把返回值给办法的调用者
- 完结该办法,在 return 后不能够再学任何语句
- 当办法体中没有 return 时,办法的返回值类型必须为 void
- 理论参数:在调用某一个具体方法 1 时,理论传递的参数值
- 如果一个须要返回值,那么肯定要保障在任何条件下都必须得有返回值
注意事项
- 办法必须定义到类中,在 java 中最小的程序单元是类
- 一个类中能够定义多个办法
- 办法和办法之间是平行的,不能在一个办法中定义另一个办法(相当于不能够在一个房子外面建房子)
- 办法定义没有先后顺序
10.2、办法的调用
如果办法有 static 润饰,能够间接用办法所在的类的类名调用,如果没有 static 润饰,那么必须应用实例化对象来调用
10.3、办法的重载
参数列表:参数的类型 + 参数的个数 + 参数的程序
办法签名:办法名称 + 办法的参数列表
在同一个类中,办法签名是惟一的,否则编译报错
办法的重载:在同一个类中,容许某办法存在一个或者多个同名的办法,然而必须参数列表不同
10.3.1、如何是否是办法重载
办法重载判断的准则:两同一不同
两同:在 同一个类中 , 办法名 是雷同 的
一不同:办法的参数列表不同(参数类型、参数个数、参数程序),只有参数类型、参数个数、参数程序其中有一个不同,都成为参数列表不同
办法的重载和返回值类型无关,只是个别都要求返回值类型雷同
10.3.2、办法重载的作用
解决了同一性能的办法因为参数不同所造成的办法名称不同而须要反复命名的问题