java规定:源文件中允许定义多个类,但只允许出现一个public修饰的类,且public修饰的类与源文件同名
// JavaFileName.java
//--------------------------
public class JavaFileNane{
...
}
class Clazz1{
...
}
class Clazz2{
...
}
java中,变量、类、方法、常量定义名称时,强制规定与潜规则同时实行
a~z A~Z 1~9 _ $ 范围内选取1name 1223namestaticName publicNameThisIsAClazzNamethisAVariable_进行分割 THIS_IS_A_CLONST_VARIABLE
概念对代码进行翻译解释的,不会被编译期解释为二进制数据
// 这是一行注释
/*
这是第一行
这是第二行
这是第三行
*/
/**
@author 作者名
@since 1.0 开发版本信息
注释内容
*/
-----------------------------
tirmal
doc.exe -> api文档
常量值 又称为字面常量,它是通过数据直接表示的,即 具体值。
整型(int)常量默认在内存中占4字节 32位,是具有整数类型的值,当运算过程中所需值超过 32 位长度时,可以把它赋值为长整型(long)数值。长整型在内存中8字节 64位。
Java 的实型常量值主要有如下两种形式。
12.34、-98.0。1.75e5 或 32&E3,其中 e 或 E 之前必须有数字,且 e 或 E 之后的数字必须为整数。Java 实型常量默认在内存中占 64 位,是具有双精度型(double)的值。如果考虑到需要节省运行时的系统资源,而运算时的数据值取值范围并不大且运算精度要求不太高的情况,可以把它表示为单精度型(float)的数值。
单精度型数值一般要在该常数后面加 F 或 f,如 69.7f,表示一个 float 型实数,它在内存中占 32 位(取决于系统的版本高低)。
Java 的字符型常量值是用单引号引起来的一个字符,如 'e'、'E'。需要注意的是,Java 字符串常量值中的单引号和双引号不可混用。引号用来表示字符串,像 "11"、"d" 等都是表示单个字符的字符串。
强调的是【单】个字符
正确'a'、'我'、'0'
错误'100'、'abcd'、'我爱你们'
描述的是一句话,也可能只有一个字,或者什么都没有
"100"、"abcd"、"我爱SH2104班所有人"
"好"
""和" "
Java 的布尔型常量只有两个值,即 false(假)和 true(真)。
true 对、真
false 错、假
null/none 不存在,没有的意思
它是内存中的一块存储区域,有 类型的限制,可以存储匹配类型的数据,并且随时可以改变其值
变量只能存储单值数据
可以改变变量空间中的数据,但类型须一致
声明同时初始化
// 数据类型 变量名 = 数据值;
int name = 101;
先声明后初始化
// 数据类型 变量名;
// 变量名 = 变量值;
double name;
name = 101;
变量一定需要声明并且初始化后才能被使用
// 错误: 可能尚未初始化变量i
int i;
System.out.println(i);
在同一个作用范围(作用域)内,不能重复定义同名的变量
// 错误: 重复定义变量 i
int i = 10;
int i = 20;
System.out.println("i=" + i);
小范围可以使用大范围内的变量,反之不行
// 错误: 找不到符号
int j = 100
{
int i = 30;
System.out.println("j=" + j);
}
System.out.println("i=" + i);
数据类型大致分为 两类
byte 占用内存1个字节(8个bit),取值范围-128~127
short 占用内存2个字节(16个bit),取值范围-3w+~3w+ 短整型
int 占用内存4个字节(32个bit),取值范围-21亿多一些~21亿多一些,主要被使用的整数型
long 占用内存8个字节(64个bit),取值范围非常大 长整型
float占用内存4个字节,称为单精度浮点数
double占用内存8个字节,称为双精度浮点数,主要被使用的浮点型
double的精度是float的一倍,小数点后面位数越多越精准
关键字 -> char,容量占用内存2个字节,符号'
关键字 -> boolean, 取值 true、false
自动/隐式类型转换:小类型 --> 大类型
byte b = 10;
short s = b; //此处发生自动类型转换
System.out.println("b=" + b + ",s=" + s);
int i = 2000;
long l = i; //此处发生自动类型转换
System.out.println("i=" + i + ",l=" + l);
---------------------------
b=10,s=10
i=2000,l=2000
强制类型转换:大类型 --> 小类型,需要使用强制类型转换符(小类型标识符)
注意强制类型转换有风险,使用需要谨慎!!
i = 600;
b = (byte)i; //此处发生强制类型转换
System.out.println("i=" + i);
System.out.println("b=" + b);
i = 5000;
s = (short)i;
System.out.println("s=" + s);
---------------------------
i=600
b=88
s=5000
数据类型之间做算数运算,如果两侧都是 int、long、float、double,结果类型和其保持一致
两个不同数据类型之间做算数运算,结果取大容量类型(99%情况)
对于 byte、short、char 之间做运算,结果为 int 类型
浮点型与整数型操作结果是浮点型,浮点型的内存容量远远大于整数型
任何数据类型和 String 类型做 + 运算,全部都是拼接操作,得到一个更长的字符串
常量不同于常量值,它可以在程序中用符号来代替常量值使用,因此在使用前必须先定义。常量与变量类似也需要初始化,即在声明常量的同时要赋予一个初始值。
常量一旦初始化就不可以被修改。它的声明格式为:
Java 语言使用 final 关键字来定义一个常量,其语法如下所示:
final dataType variableName = value
final 关键字表示最终的,它可以修饰很多元素,修饰变量就变成了常量。例如,以下语句使用 final 关键字声明常量。
public class HelloWorld {
// 静态常量
public static final double PI = 3.14;
// 声明成员常量
final int y = 10;
public static void main(String[] args) {
// 声明局部常量
final double x = 3.3;
}
}
常量有三种类型:静态常量、成员常量和局部常量。
代码第 3 行的是声明静态常量,使用在 final 之前 public static 修饰。public static 修饰的常量作用域是全局的,不需要创建对象就可以访问它,在类外部访问形式为 HelloWorld. PI。
代码第 5 行声明成员常量,作用域类似于成员变量,但不能修改。
代码第 9 行声明局部常量,作用域类似于局部变量,但不能修改。
在定义常量时,需要注意如下内容:
final 关键字不仅可以用来修饰基本数据类型的常量,还可以用来修饰对象的引用或者方法。当常量被设定后,一般情况下不允许再进行更改,如果更改其值将提示错误。
+ - * / %
/操作,做取整操作%操作,结果的正负号和被模数相同++ --
++的左侧(前面),先做其它操作,再做自增操作++的右侧(后面),先做自增操作,再做其它操作> >= < <= == !=
>=和<=而言,只要满足两个条件中的任何一个,结果就为true+= -= *= /= %=
int i = 3;
int j = 5;
j *= i++ + j; //毫无意义 实际代码中如果这么写 会被喷死
逻辑运算符操作运算的表达式都是布尔值,最终得到的结果也是布尔值
逻辑与 &
短路与 && ,当左边为假 不会继续判断 右边
true 与 true 结果为true
true 与 false 结果为false
false 与 true 结果为false
false 与 false 结果为false
总结与操作对false敏感,一假即假
逻辑或|
短路或|| ,当 左边为真 不会继续判断 右边表达式
true 或 true 结果为true
true 或 false 结果为true
false 或 true 结果为true
false 或 false 结果为false
总结或操作对true敏感,一真即真
对于逻辑操作而言执行完第一个表达式,即使满足了敏感结果,也会执行第二个表达式
对于短路操作而言执行完第一个表达式,如果满足了敏感结果,不会执行第二个表达式
^
true ^ true 结果为false
true ^ false 结果为true
false ^ true 结果为true
false ^ false 结果为false
总结相异为真,异或追求的就是这个"异"字
符号!
总结取反操作
条件表达式 ? 表达式1 : 表达式2;
jvm会先执行条件表达式,
如果条件表达式的结果为true, 就执行表达式1,并且将表达式1的运行结果做为整个三目运算的最终结果
如果条件表达式的结果为false,就执行表达式2,并且将表达式2的运行结果做为整个三目运算的最终结果
| 运算符 | 结合性 |
|---|---|
[ ] . ( ) (方法调用) | 从左向右 |
! ~ ++ -- +(一元运算) -(一元运算) | 从右向左 |
* / % | 从左向右 |
+ - | 从左向右 |
> >>> | 从左向右 |
< >= instanceof | 从左向右 |
== != | 从左向右 |
& | 从左向右 |
^ | 从左向右 |
| ` | ` |
&& | 从左向右 |
| ` | |
? : | 从右向左 |
= | 从右向左 |
分类格式(3种)
1
if(条件表达式){
2
}
3
1
if(条件表达式){
2
}else{
3
}
4
①
if(条件表达式1){
②
}else if(条件表达式2){
③
}else if(条件表达式n){
④
}else{
⑤
}
格式
switch(表达式){
case 值1
语句块1;
case 值2
语句块2;
...
default
语句块n;
}
注意事项
switch小括号中的表达式是有类型限制的,只能使用byte、short、char、int、枚举Enum(JDK5)、字符串String(jdk7)
按照顺序结构从上往下依次匹配每个case后面的值
多数情况每个 case 后面需要显示的定义 break 关键字,防止 case 穿透现象;
default 是可选的,位置是随意的,但是一般定义在最后位置
default 是最后才被执行的
int i = 12;
switch(i){
case 0:
System.out.println("zero");
break;
case 1:
System.out.println("one");
break;
case 2:
System.out.println("two");
break;
...
default:
System.out.println("other");
break;
}
循环的四要素
true还是false,决定是否继续执行循环格式
①
while(②){
④
③
}
执行顺序① -> ② -> ④ -> ③ -> ② -> ④ -> ③ -> ② -> 整个循环结构
int i = 1; //初始化部分
while(i >= 10){ //循环部分
System.out.println("Hello World!"); //循环体
i++; //迭代部分
}
格式
①
do{
④
③
}while(②);
while和do…While的区别
对于while循环而言,如果第一次循环条件的判断就为false,那么循环体和迭代条件就一次都不会执行
对于do...while循环而言,不管怎么样,都会先执行一次循环体和迭代条件,再进行循环条件的判断;
int i = 10;
while(i < 10){
System.out.println("我是while循环的循环体");
i++;
}
do{
System.out.println("我是dowhile循环的循环体");
i++;
}while(i < 10);
for(①;②;③){
④
}
while 中 while
while 中 for
...
for 中 for
//外层循环
for(){
//内层循环
for(){
}
}
表示的是一段逻辑功能代码,有自己独立的作用范围(作用域),并且有自己的名字,需要通过方法名才能对其进行调用
解决代码复用性差的问题(提高了程序中代码的复用性)
① ② ③ (④){
⑤
}
①.修饰符 public static
②.返回值类型 无返回值(void)/有返回值
③.方法名 标识符之一(满足规则和规范),为了区分当前类的其它方法的
④.形参列表 有参/无参; 分析 --> 定义数据类型和变量名,为了在调用方法的时候接受实际传入的数据
⑤.方法体 需要执行的功能逻辑代码
形式参数(形参):定义的位置形参列表后面,存在的意义就是指代实际参数,描述函数入参,描述业务逻辑
实际参数(实参):在方法被调用时传递给方法的值,用于运算的值
return的作用有两个
1. 将return后面的数据返回给方法的调用处
2. 结束方法
3. return关键字后面(同一作用范围)不能出现任何的代码,因为其永远不可能被执行到
for(int i = 1;i <= 5;i++){
for(int j = 1;j <= 10;j++){
if(j % 4 == 0) break ;
System.out.print(j);
}
System.out.println();
}
for(int i = 1;i <= 5;i++){
for(int j = 1;j <= 10;j++){
if(j % 4 == 0) continue;
System.out.print(j);
}
System.out.println();
}
label:for(int i = 1;i <= 5;i++){
for(int j = 1;j <= 10;j++){
if(j % 4 == 0){
break label;
}
System.out.print(j);
}
System.out.println();
}
/*
break的执行效果
123
123
123
123
123
continue的执行效果
123567910
123567910
123567910
123567910
123567910
break配合标签的执行效果
123
*/
for(int i = 1;i < 11;i++){
if(i % 4 == 0){
break;
//continue;
/*
break/continue关键字后面(同一作用范围)不能出现任何的代码,因为其永远不可能被执行到
*/
}
System.out.print(i);
}
//定义无参无返回值的方法
public static void m1(){
System.out.println("方法有五要素组成!");
return;
}
//定义无参有返回值的方法
public static String m2(){
//在自定义方法中调用别的自定义方法
m1();
return "马上就要休息了";
}
//定义有参无返回值的方法
public static void m3(int i){
if(i % 2 == 0){
System.out.println("是偶数");
}else{
System.out.println("是奇数");
}
}
//定义有参有返回值的方法
public static int m4(int a,int b){
return a > b ? a : b;
}
数组是一种容器,是内存中一块连续的存储空间,内部有一组连续的小空间;有数据类型的限定,可以存储一组相同类型的数据;解决变量只能存储单个数据的局限性,并且对一组数据的维护和管理
静态初始化
将数组定义&创建\分配内存空间和为数组元素赋值同时进行
数据类型[] 数组名 = new 数据类型[]{数据1,数据2,...,数据n};
int[] arr = new int[]{10,20,30,40,50};
int[] arr = {10,20,30,40,50};
动态初始化
将数组定义&创建\分配内存空间和为数组元素赋值分开进行
数据类型[] 数组名 = new 数据类型[容量/长度];
数组名[下标] = 数据;
int[] arr = new int[6];
arr[2] = 99;
数组元素第一个下标是0开始的
//静态初始化
int[] scores = new int[]{50,60,70,80,90};
//动态初始化
String[] names = new String[3];
//访问数组元素设置值
names[0] = "张三";
//访问数组元素获取值
System.out.println(names[0]);
//数组有length属性获取scores数组的长度
System.out.println(scores.length); //5
for(int i = 0;i<= scores.length - 1;i++){
//数组名配合下标得到数组元素
System.out.println(scores[i]);
}
对于基本数据类型
整数型byte、short、int、long --> 0
int[] arr = new int[4];
for(int i = 0;i <= arr.length - 1;i++){
System.out.println(arr[i]); //0
}
byte[] bs = new byte[4];
for(int i = 0;i <= bs.length - 1;i++){
System.out.println(bs[i]); //0
}
浮点型float、double --> 0.0
double[] ds = new double[4];
for(int i = 0;i <= ds.length - 1;i++){
System.out.println(ds[i]); //0.0
}
布尔型boolean --> false
boolean[] bools = new boolean[4];
for(int i = 0;i <= bools.length - 1;i++){
System.out.println(bools[i]); //false
}
字符型char --> 空白字符
char[] cs = new char[4];
for(int i = 0;i <= cs.length - 1;i++){
System.out.println(cs[i]); //'\u0000' --> 空白符
}
对于引用数据类型默认值都是null
/*
对于引用数据类型而言默认值都为null
*/
String[] strs = new String[4];
for(int i = 0;i <= strs.length - 1;i++){
System.out.println(strs[i]); //null
}
//自定义对象数组pers
Person[] pers = new Person[4];
for(int i = 0;i <= pers.length - 1;i++){
System.out.println(pers[i]); //null
}
//创建一个人,存入到1索引位置上
pers[1] = new Person();
for(int i = 0;i <= pers.length - 1;i++){
System.out.println(pers[i]);
}
//自定义类人类
//自定义类型也是引用类型
class Person
{
//...
}
new出来的"东西"都在堆中,堆中的变量都有默认值,并且都有一个地址值
/*
演示数组的内存执行过程
*/
class TestArray03
{
public static void main(String[] args)
{
int[] arr = new int[4];
arr[2] = 10;
System.out.println("arr=" + arr); //arr=[I@15db9742
System.out.println("arr[0]=" + arr[0]); //0
System.out.println("arr[2]=" + arr[2]); //10
}
}
使用数组常见的异常情况(运行时异常)
java.lang.ArrayIndexOutOfBoundsException --> 数组的下标越界异常
java.lang.NullPointerException --> 空指针异常
int[] arr = new int[10];
/*
Exception in thread "main" `java`.lang.ArrayIndexOutOfBoundsException: 10
运行时异常 --> 数组的下标越界异常
*/
//System.out.println(arr[10]);
//System.out.println(arr[-10]);
arr = null;
/*
Exception in thread "main" `java`.lang.NullPointerException
运行时异常 --> 空指针异常
空指针异常的第一种情况
*/
//System.out.println(arr[0]);
/*
空指针异常的第二种情况
注意只要是null,显式地通过.的形式调用属性或者方法,都会出现空指针
*/
System.out.println(arr.length);
数组一旦创建其长度不可变
int[] arr = {11,22,33,44,55,66};
//定义新数组arr1,长度为arr.length + 2
int[] arr1 = new int[arr.length + 2];
//1.先将arr中原本的数组复制到arr1中
for(int i = 0;i <= arr.length - 1;i++){
arr1[i] = arr[i];
}
//2.单独加入77和88到arr1最后两个元素中
arr1[arr1.length - 2] = 77;
arr1[arr1.length - 1] = 88;
/*
遍历arr1数组
*/
for(int i = 0; i < arr1.length;i++){
System.out.println(arr1[i]);
}
静态初始化
数据类型[][] 数组名 = new 数据类型[][]{数据1,数据2,...,数据n};
int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8}};
简化版
`数据类型[][] 数组名 = {数据1,数据2,...,数据n};`
```java
int[][] arr = {{1,2,3},{4,5,6},{7,8}};
动态初始化
数据类型[][] 数组名 = new 数据类型[行数/一维数组的个数][列数/每一个一维数组对应的列数];
举例
```java
int[][] arr = new int[4][4]; //表示有4个一维数组,并且每个一维数组有4个元素
// 第一步
数据类型[][] 数组名 = new 数据类型[行数/一维数组的个数][];
// 第二步
分别为每一个一维数组创建对象,目的确定它们各自的长度
数组名[行数] = new 数据类型[长度];
// 第三步
确定每一个一维数组中的元素值,一般可以使用循环操作
String[][] arr = new String[3][];
String[0] = new String[4];
String[1] = new String[2];
String[2] = new String[3];
示例
class TestArrayArray02
{
public static void main(String[] args)
{
//定义二维数组(一维数组的个数不同)
int[][] arr = new int[5][];
//分别为每一个一维数组确定其个数
for(int i = 0;i <= arr.length - 1;i++){
arr[i] = new int[i + 1];
}
//为每一个一维数组中的每个元素赋值
for(int i = 0;i <= arr.length - 1;i++){
for(int j = 0;j <= arr[i].length - 1;j++){
arr[i][j] = i + 1;
}
}
//遍历二维数组
for(int i = 0;i <= arr.length - 1;i++){
for(int j = 0;j <= arr[i].length - 1;j++){
System.out.print(arr[i][j]);
}
System.out.println();
}
}
}
/*
执行效果如下
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
*/
遍历
a. 一维数组遍历
import `java`.util.Scanner;
class TestArray07
{
public static void main(String[] args)
{
System.out.println("需要创建的数组长度为");
Scanner input = new Scanner(System.in);
int size = input.nextInt();
int[] arr = new int[size];
//调用prepare方法准备数据
prepare(arr);
//调用printArray方法查看内容
printArray(arr);
}
public static void prepare(int[] arr){
Scanner input = new Scanner(System.in);
for(int i = 0;i <= arr.length - 1;i++){
System.out.println("请为第" + (i + 1) + "个元素赋值");
arr[i] = input.nextInt();
}
}
public static void printArray(int[] arr){
for(int i = 0;i < arr.length;i++){
if(i == arr.length - 1){
System.out.print(arr[i]);
}else{
System.out.print(arr[i] + ",");
}
}
System.out.println();
}
}
b. 二维数据遍历
class TestArrayArray01
{
public static void main(String[] args)
{
//定义二维数组(还没有元素)
int[][] arr = new int[5][5];
//为每一个一维数组元素赋值
//外层循环控制行数,5个一维数组,5行
for(int i = 0;i <= arr.length - 1;i++){
//内层循环控制列数,每一个一维数组的元素
for(int j = 0;j <= arr[i].length - 1;j++){
arr[i][j] = i + 1;
}
}
//遍历二维数组
for(int i = 0;i <= arr.length - 1;i++){
for(int j = 0;j <= arr[i].length - 1;j++){
System.out.print(arr[i][j]);
}
System.out.println();
}
}
}
/*
执行效果如下
1 1 1 1 1 index:0
2 2 2 2 2 index:1
3 3 3 3 3 ...
4 4 4 4 4
5 5 5 5 5
*/
一维数组求最值、求和、平均值
class TestArray08
{
public static void main(String[] args)
{
int[] arr = {29,99,100,-17,82,10};
//调用getArrayMax得到最大值
int max = getArrayMax(arr);
System.out.println("数组的最大值为" + max);
int sum = getArraySum(arr);
System.out.println("数组的总和为" + sum);
double avg = getArrayAVG(arr);
System.out.println("数组的平均值为" + avg);
}
public static int getArrayMax(int[] arr){
int max = arr[0]; //此处的max记录为了数组中的最大值,并且假设第一个元素是最大的
//循环比较大小
for(int i = 1;i <= arr.length - 1;i++){
if(max < arr[i]){
//重新为max赋值
max = arr[i];
}
}
return max;
}
public static int getArraySum(int[] arr){
int sum = 0;
for(int i = 0;i <= arr.length - 1;i++){
sum += arr[i]; //sum = sum + arr[i];
}
return sum;
}
public static double getArrayAVG(int[] arr){
//调用自定义函数getArraySum,得到总和
return getArraySum(arr) * 1.0 / arr.length;
}
}