JAVA基础
Java概述
Java是一门面向J对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。
Java具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点 。Java可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式系统应用程序等。(百度百科)
理解JAVA可以从JVM、JRE、JDK的作用去理解。
JVM – Java Vartual Machine,Java虚拟机,主要功能将.java文件编译后的.class文件进行解释执行。
JRE – Java Runtime Environment, Java运行时环境,提供了Java代码运行起来的所有依赖。包含JVM。
JDK – Java Development Kit,Java开发工具包,用基础语法构建了大量的工具库,为软件开发提供了便捷的思路,是所有Java程序员的规范包,每次版本更新都是一次规范的升级。包含JRE。
JAVA文件运行过程如图,从一个.java文件通过编译(javac)后变成.class文件,然后通过JVM的类加载器把class文件解释成机器语言,执行代码调用操作系统,操作系统再调用硬件接口,完成输入输出。
Java安装
JDK1.8下载 https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html
IDEA下载 https://www.jetbrains.com/idea/download/
配置环境变量:
JAVA_HOME:D:\JAVA\jdk1.8.0_271
Path:%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
CLASSPATH:.;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar
# 特别的,如果是win10系统,Path配置的时候不能%JAVA_HOME%,要用绝对路径,不然cmd里面运行javac会报错
JAVA_HOME:D:\JAVA\jdk1.8.0_271
Path:D:\JAVA\jdk1.8.0_271\bin;D:\JAVA\jdk1.8.0_271\jre\bin
CLASSPATH:.;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar
通过cmd窗口,java -version、javac验证
C:\Users\Z>java -version
java version "1.8.0_271"
Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)
C:\Users\Z>javac
用法: javac <options> <source files>
其中, 可能的选项包括:
-g 生成所有调试信息
-g:none 不生成任何调试信息
-g:{lines,vars,source} 只生成某些调试信息
dos命令
在桌面新建一个Hello.java文件
public class Hello {
public static void main(String[] args) {
System.out.println("helloworld");
}
}
去cmd窗口运行dos命令
C:\Users\Z>D:
D:\>cd Desktop
# 编译java文件,完成后桌面会多一个class文件
D:\Desktop>javac Hello.java
# 然后将class文件解释
D:\Desktop>java Hello
helloworld
注释
单行注释:用于注释单行代码
//单行注释
多行注释:用于注释多行代码
/*
多行注释
*/
文本注释:用于javadoc
/**
* @author
* @param
* @since
* @version
*/
关键字
Java 语言目前定义了 51 个关键字,这些关键字不能作为变量名、类名和方法名来使用。以下对这些关键字进行了分类。(下表来源于百度百科)
- 数据类型:boolean、int、long、short、byte、float、double、char、class、interface
- 流程控制:if、else、do、while、for、switch、case、default、break、continue、return、try、catch、finally
- 修饰符:public、protected、private、final、void、static、strict、abstract、transient、synchronized、volatile、native
- 动作:package、import、throw、throws、extends、implements、this、supper、instanceof、new。
- 保留字:true、false、null、goto、const
关键字 | 含义 |
---|---|
abstract | 表明类或者成员方法具有抽象属性 |
assert | 断言,用来进行程序调试 |
boolean | 基本数据类型之一,声明布尔类型的关键字 |
break | 提前跳出一个块 |
byte | 基本数据类型之一,字节类型 |
case | 用在switch语句之中,表示其中的一个分支 |
catch | 用在异常处理中,用来捕捉异常 |
char | 基本数据类型之一,字符类型 |
class | 声明一个类 |
const | 保留关键字,没有具体含义 |
continue | 回到一个块的开始处 |
default | 默认,例如,用在switch语句中,表明一个默认的分支。 |
do | 用在do-while循环结构中 |
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 | 用来声明FP_strict(单精度或双精度浮点数)表达式遵循算术规范 |
super | 表明当前对象的父类型的引用或者父类型的构造方法 |
switch | 分支语句结构的引导词 |
synchronized | 表明一段代码需要同步执行 |
this | 指向当前实例对象的引用 |
throw | 抛出一个异常 |
throws | 声明在当前定义的成员方法中所有需要抛出的异常 |
transient | 声明不用序列化的成员域 |
try | 尝试一个可能抛出异常的程序块 |
void | 声明当前成员方法没有返回值 |
volatile | 表明两个或者多个变量必须同步地发生变化 |
while | 用在循环结构中 |
标识符
Java 中标识符是为方法、变量或其他用户定义项所定义的名称。标识符可以有一个或多个字符。在 Java 语言中,标识符的构成规则如下。
- 标识符由数字(0-9)和字母(A-Z 和 a-z)、美元符号($)、下划线(_)以及 Unicode 字符集中符号大于 0xC0 的所有符号组合构成(各符号之间没有空格)。
- 标识符的第一个符号为字母、下划线和美元符号,后面可以是任何字母、数字、美元符号或下划线。
数据类型
计算机中最小存储单位是字节,1Byte=8bit
整数类型
byte (1个字节) [-2^7 ,2^7)
short(2个字节) [-2^15 ,2^15)
int (4个字节) [-2^31 ,2^31)
long(8个字节) [-2^63 ,2^63)
小数类型
float(4个字节) [-2^31 ,2^31)
double(8个字节) [-2^63 ,2^63)
字符类型
char(2个字节) [-2^15 ,2^15)
布尔类型
boolean (1个字节) [-2^7 ,2^7)
常量与变量
主要和内存存储有关。
常量的定义:在程序运行过程一直不会改变的量称为常量,通常也成为"final变量"。常量在整个程序中只能被赋值一次。如果某个数据需要被所有的对象共享时,建议采用常量。声明常量的标准语法:final 数据类型 变量名[=值]
-
常量名通常使用大写字母,但这不是必须。为了代码规范,建议声明变量的时候采用大写字母。
-
当定义的final变量为成员变量时,必须在定义时就设定它的初始值,否则将会提示编译错误。
变量的定义:定义变量就是要告诉编译器这个变量的数据类型,这样编译器才知道需要分配多少空间给它,以及它能存放什么样的数据。在程序运行过程中空间的值是变化的,这个内存空间就成为变量。为了便于操作,给这个变量取个名字,称为变量名。
-
不能和关键字冲突
-
变量名不能重复且需要有意义
运算符
算术运算符
操作符 | 名称 | 描述 |
---|---|---|
+ | 加法 | 相加运算符两侧的值 |
– | 减法 | 左操作数减去右操作数 |
* | 乘法 | 相乘操作符两侧的值 |
/ | 除法 | 左操作数除以右操作数 |
% | 取余 | 左操作数除以右操作数的余数 |
++ | 自增 | 操作数的值增加1,单目运算符 |
– | 自减 | 操作数的值减少1,单目运算符 |
关系运算符
操作符 | 名称 | 描述 |
---|---|---|
> | 大于 | 相加运算符两侧的值 |
< | 小于 | 左操作数减去右操作数 |
== | 等于 | 相乘操作符两侧的值 |
>= | 大于等于 | 左操作数除以右操作数 |
<= | 小于等于 | 左操作数除以右操作数的余数 |
!= | 不等于 | 操作数的值增加1 |
位运算符
操作符 | 名称 | 描述 |
---|---|---|
& | 按位& | 如果相对应位都是1,则结果为1,否则为0 |
| | 按位或 | 如果相对应位都是0,则结果为0,否则为1。 |
^ | 异或 | 如果相对应位值相同,则结果为0,否则为1 |
~ | 按位取反 | 翻转操作数的每一位,即0变成1,1变成0。结果为: -(X+1) |
<< | 按位左移 | 通常格式为:value << num,value按位左移num位 |
>> | 有符号按位右移 | 通常格式为:value >> num,value按位右移num位。 |
>>> | 无符号按位右移 | 通常格式为:value >> num,value按右移num位,移动得到的空位以零填充。 |
逻辑运算符
操作符 | 名称 | 描述 |
---|---|---|
&& | 短路与 | 当且仅当两个操作数都为真,条件才为真。 |
& | 逻辑与 | 当且仅当两个操作数都为真,条件才为真。 |
| | | 短路或 | 如果任何两个操作数任何一个为真,条件为真。 |
| | 逻辑或 | 如果任何两个操作数任何一个为真,条件为真。 |
! | 逻辑非 | 用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false |
赋值运算符
操作符 | 名称 | 描述 |
---|---|---|
= | 赋值 | 右操作数的值赋给左侧操作数 |
+= | 加和赋值 | a+=b 等同于 a = a+b |
-= | 减和赋值 | a-=b 等同于 a = a-b |
*= | 乘和赋值 | a*=b 等同于 a = a*b |
/= | 除和赋值 | a/=b 等同于 a = a/b |
%= | 取模和赋值 | a%=b 等同于 a = a%b |
instanceof 运算符
instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
# 结果都是true
public class InstanceofDemo {
public static void main(String[] args) {
String name = "zbk";
System.out.println(name instanceof String);
System.out.println(name instanceof Object);
}
}
优先级
- 括号级别最高,逗号级别最低;
- 单目 > 算术 > 位移 > 关系 > 逻辑 > 三目(boolean表达式 ? 表达式1 : 表达式2) > 赋值。注:为了代码逻辑清晰,建议多用括号;
- 除了单目运算符、赋值运算符和条件运算符,其他的运算符都是从左到右运算的。
流程控制语句
if语句
public class IfDemo {
public static void main(String[] args) {
getMax(1,2);
}
public static void getMax(int a,int b){
if(a == b){
System.out.println(a+"="+b);
}else if (a > b){
System.out.println(a+">"+b);
}else {
System.out.println(a+"<"+b);
}
}
}
switch-case语句
public class CaseDemo {
public static void main(String[] args) {
getGrade('A');
}
public static void getGrade(char score){
switch (score){
case 'A' :
System.out.println("优秀");
break;
case 'B' :
System.out.println("及格");
break;
case 'C' :
System.out.println("不及格");
break;
}
}
}
while语句
public class WhileDemo {
public static void main(String[] args) {
int result = getSum(0);
System.out.println(result);
}
public static int getSum(int n){
int sums = 0;
while(n > 0){
sums += n;
n--;
}
System.out.println(n);
return sums;
}
}
do-while语句
public class DoWhileDemo {
public static void main(String[] args) {
int result = getSum(0);
System.out.println(result);
}
public static int getSum(int n){
int sums = 0;
do{
sums += n;
n--;
}while (n > 0);
System.out.println(n);
return sums;
}
}
for语句
public class ForDemo {
public static void main(String[] args) {
int result = getSum(5);
System.out.println(result);
}
public static int getSum(int n){
int sums = 0;
for (int i=1 ; i < n+1; i++) {
sums += n;
}
return sums;
}
}
方法
Java中的方法(在其他语言中有的叫函数function)不能独立存在,所有的方法都必须定义在类里。执行方法时必须使用类或者对象来作为调用者,所有的方法都必须使用“类.方法”或“对象.方法”的形式调用。
方法(method)的作用是对一些功能类似的代码进行一个封装,{}内的代码就是这个方法的功能。比如说求前n项整数和。在主函数直接调用方法名(参数)就可以使用这个方法了。方法主要是为了简化冗余代码,而jdk中有大量基础类方法的目的就是为了避免重复造轮子。可以类比,为了实现搭建一个城堡,我们需要很多积木,每个积木就是一个方法。
# 举个例子,求n项整数和的方法getSum,定义好方法以后我们就可以在main方法中直接调用了
public class MethodDemo {
public static void main(String[] args) {
int result = getSum(5);
System.out.println(result);
}
public static int getSum(int n){
int sums = 0;
for (int i=1 ; i < n+1; i++) {
sums += n;
}
return sums;
}
}
规范
首先方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
-
修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型或者说访问范围。
public 对所有类可见。使用对象:类、接口、变量、方法
protected 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
default 即默认,在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
修饰符 当前类 同一包内 子孙类(不同包) 其他包 public Y Y Y Y protected Y Y Y N default Y Y N N private Y N N N -
返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
-
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
-
参数列表:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
-
方法体:方法体包含具体的语句,定义该方法的功能。
重载
方法名一致,参数列表不同。Java是强类型语言,调用每个方法的时候,编译器会把实参同形参校验。重载的主要作用是为了解决参数需求可变的情况。
# 定义一个类
public class Dogs {
String type;
int age;
# 构造方法重载
public Dogs(String type, int age) {
this.type = type;
this.age = age;
System.out.println("构造方法重载:"+type+age);
}
public Dogs(int age) {
this.age = age;
System.out.println("构造方法重载:"+age);
}
public Dogs(String type) {
this.type = type;
System.out.println("构造方法重载:"+type);
}
public Dogs() {
System.out.println("构造方法重载");
}
# 普通方法重载
# 重载方法1
public void getDog(String type){
this.type = type;
System.out.println("方法重载,有一只"+this.type);
}
# 重载方法2
public void getDog(int age){
this.age = age;
System.out.println("方法重载,有一只"+this.age+"岁的狗");
}
# 重载方法3
public void getDog(String type,int age){
this.type = type;
this.age = age;
System.out.println("方法重载,有一只"+this.age+"岁的"+this.type+"狗");
}
}
# 调用
public class Application {
public static void main(String[] args) {
Dogs d1 = new Dogs(2);
Dogs d2 = new Dogs("泰迪",3);
Dogs d3 = new Dogs("拉布拉多");
d1.getDog(2);
d2.getDog("泰迪",3);
d3.getDog("拉布拉多");
}
}
# 输出结果
构造方法重载:2
构造方法重载:泰迪3
构造方法重载:拉布拉多
方法重载,有一只2岁的狗
方法重载,有一只3岁的泰迪狗
方法重载,有一只拉布拉多
如果只想了解狗的种类,就调用重载方法1;如果只想了解狗的年龄,就调用重载方法2;如果即想了解狗的种类又想了解狗的年龄,就调用重载方法3。通过上面这个例子可以理解重载运用的场景,也就是重载的作用。
数组
概念
同一种数据类型的集合。八大基本类型不能存储2个以上的数据,所以Java需要增加数组这样的一个容器来存储大量数据。
常见用法
创建数组
元素类型[] 数组名 = new 元素类型[元素个数或数组长度]
元素类型 数组名[] = new 元素类型[元素个数或数组长度]
元素类型[] 数组名 = new 元素类型[]{元素,元素,……}
元素类型 数组名[] = new 元素类型[]{元素,元素,……}
# 定义一个长度为5的空数组
int[] a = new int[5];
int b[] = new int[5];
# 定义一个长度为5的数据组,且1,2,3,4,5为数据的数据
int[] c = {1,2,3,4,5}
int[] d = new int[]{1,2,3,4,5}
调用数组
# 调用数组
public class ArrayDemo {
public static void main(String[] args) {
int[] a = new int[]{1,2,3,4,5};
# index的最大长度为4,如果超过数组最大长度,会抛出异常ArrayIndexOutOfBoundsException
System.out.println(a[0]);
}
}
# 输出结果
1
遍历数组
public class ArrayDemo {
public static void main(String[] args) {
int[] a = new int[]{1,2,3,4,5};
# for循环遍历
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]+"\t");
}
System.out.println();
# 增强for循环遍历
for(int x:a){
System.out.print(x+"\t");
}
# 调用Arrays的toString方法
System.out.println();
System.out.println(Arrays.toString(a));
}
}
# 输出结果
1 2 3 4 5
1 2 3 4 5
[1, 2, 3, 4, 5]
多维数组
数组内部嵌套数组的方式,有点像递归。以数组的遍历为例
# 二维数组遍历
public class ArrayDemo {
public static void main(String[] args) {
int[][] array = {{1,2},{3,4},{5,6}};
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length ; j++) {
System.out.print(array[i][j]+"\t");
}
}
}
}
# 三维数组遍历
public class ArrayDemo {
public static void main(String[] args) {
int[][][] array = {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}};
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length ; j++) {
for (int k = 0; k < array[i][j].length; k++) {
System.out.print(array[i][j][k]+"\t");
}
}
}
}
}