一、初识Java与Java程序剖析
1、JDK环境配置
关于JDK环境的配置,前面文章有提到过Android逆向-002.Android开发环境搭建
2、IntelliJ IDEA集成开发环境
IntelliJ IDEA是Java编程语言开发的集成环境。
下载:IntelliJ IDEA
3、Java程序剖析(从HelloWorld说起)
应用程序的主类:一个Java程序的源文件必须包含一个public static void main(String args[])方法,这个方法被称为应用程序的入口方法,args[]是main方法的参数,是一个字符串类型的数组,用来存储输入的参数。
源文件的命名:源文件名字必须与类的名字相同,扩展为.java,注意:Java区分大小写。
Java一般命名规则:
- 包的命名:全部小写(com.xxx.xx)
- 类的命名:单词首字母大写,如果由多个单词组成则每个单词首字母大写。(HelloWorld)
- 变量/方法的命名:首字母小写,如果由多个单词组成,则除第一个单词外,其余每个单词首字母大写。(getName)
- 常量的命名:全部大写,常加入下划线(MAX_VALUE)
所有命名规则必须遵循以下规则:
- 1.名称只能由字母、数字、下划线、$符号组成。
- 2.不能以数字开头
- 3.名称不能使用Java的关键字。
举例:将以下代码保存为HelloWorld.java
public class HelloWorld{
public static void main(String args[]){
int outValue = 1;
System.out.println("hello world: "+outValue);
}
}
编译:
javac.exe HelloWorld.java
生成:
ls
HelloWorld.class HelloWorld.java
运行:
java HelloWorld
hello world: 1
Java相对于C/C++的优点:支持跨平台、Java有内置的垃圾回收机制、更安全。
Java的跨平台运行机制:
Java语言的源程序->编译成Java字节码->通过JVM虚拟机进行解释执行从而实现跨平台运行
Java关键字:51个使用中,2个保留关键字(const、goto)所以共53个关键字。
访问控制:
- private 私有的、protected 受保护的、public 公开的
类,方法和变量修饰符:
- abstract 声明抽象类、class 类、extends 扩充,继承、final 终极,不可改变的、implements 实现、interface 接口、native 本地、new 创建、static 静态、strictfp 严格,精准、synchronized 线程同步、transient 短暂、volatile 易失
程序控制语句:
- break 跳出循环、continue 继续、return 返回、do 运行、while 循环、if 如果、else 反之、for 循环、instanceof 实例、switch 开关、case 开关的结果、default 默认
错误处理:
- try 捕获异常、catch 处理异常、finally 有没有异常都执行、throw 抛出一个异常对象、throws 声明一个异常可被抛出、assert 断言
包相关:
- import 引入、package 包
基本类型:
- boolean 布尔型、byte 字节型、char 字符型、double 双精度、float 浮点、int 整数、long 长整型、short 短整型、null 空、true 真、false 假、enum 枚举
变量引用:
- super 父类,超类、this 本类、void 无返回值
二、数据类型和基本操作
Java提供了两类数据类型,一类是基本数据类型(原始类型),一类是引用类型。
1、基本数据类型
Java语言中一共有8种基本数据类型,分别是:boolean、byte、short、int、long、float、double、char
分为四大类:
布尔类型:boolean(C/C++中的逻辑类型是bool)
- 常量:true、false
- 变量:使用关键字boolean来声明逻辑变量,声明时可以直接赋初始值。
整数类型:byte,short,int,long
- int:Java中的int型常量可以直接写值:比如120,int型变量需要使用关键字int来声明
- byte:Java中不存在byte类型的常量,但是可以将一定范围内的int型常量赋值给byte型变量,通过byte关键字可以来声明byte型变量
- short:和byte类型一样,Java中不存在short类型常量,但可以把一定范围内的int型常量赋值给short型变量。
字符类型:char
- char:用单引号括起来的unicode表中的字符
浮点类型:float、double
- float:内存分配4个字节的浮点数,占32位
- double:内存分配8个字节的浮点数,占64位
2、变量,常量以及赋值语句
变量:在程序运行过程中可以发生改变的
- 声明语法格式:数据类型 变量名 = 值;
常量:在程序运行过程中不能改变的,程序运行前就被初始化的。
- 常量的语法格式,只需要在变量的语法格式前面添加关键字final即可。常量名必须大写。
- final关键字用于声明常量,方法和类,含义是"这是无法改变的"或"最终状态"
- final 数据类型 常量名 = 值;举例:final double P=3.14;final int MIN_VALUE=0;
- final修饰的常量只能被赋值一次,赋值后值不可以再改变。
- final修饰的方法不能被子类方法重写,但是可以被继承。
- final修饰的类不能被继承,没有子类,final类中所有方法都是final的。
Java的赋值语句是"="号,举例int变量赋值:int a=1;表示声明一个int型变量a,并将1赋值给a。除了可以将数值常量赋值还支持将变量赋值给变量,举例:int b=a;表示声明一个int型变量并将变量a的值赋值给变量b。注意这里的变量a需要与变量b类型一致,类型不一致的变量赋值需要类型转换,别的类型赋值与此类似。
3、数据类型转换
基本类型大小:从小到大
- byte:字节型:占1字节
- boolean:布尔型:占1字节
- char:字符型:占1字节
- short:短整型:占2字节
- int:整型:占4字节
- float:单精度浮点型:占4字节
- long:长整型:占8字节
- double:双精度浮点型:占8字节
自动(隐私)类型转换:自动将小类型转换为大类型,不需要强制转换符
举例:int a = 5;double b = a;
此处将占4字节大小的int类型变量a的值赋值给了占8字节大小的double类型变量b,因为a是小类型转为大类型,所以int类型变量a的值会自动转为double类型并赋值给变量b。
强制类型转换:将大类型转换为小类型,需要通过强制转换符来实现强制转换。
举例:double a = 520.1314;int b = (int)a;
此处将占8字节大小的double类型变量a赋值给占4字节大小的int类型变量b,因为是大类型转为小类型,所以double型变量a需要先强制转为int类型变量才能赋值给int型变量b。
注意:强转可能产生精度丢失,例如double类型变量a值为520.1314,强转成int类型后数值将会变成520,强转导致小数位舍弃产生精度丢失。
4、引用数据类型
在Java中除去基本数据类型的其他类型都是引用类型,包括自定义的class类,引用类型指向一个对象,不是原始的值,指向对象的变量是引用变量。
引用类型常见的有:String、StringBuffer、ArrayList、HashSet、HashMap等。
5、枚举
定义枚举:
使用enum声明枚举类型:
enum名字{
常量列表
}
其中常量列表用逗号分隔的字符序列,称为枚举类型的常量。
示例:
enum Season{
spring,summer,autumn,winter
}
上面声明了名字为Season的枚举类型,该枚举类型有4个常量。
枚举变量:
声明了名字为Season的枚举类型,该枚举类型有4个常量。
声明了一个枚举类型后,就可以用该枚举类型声明一个枚举变量。
示例:
Season x;该枚举变量只能取值枚举类型中的常量。通过使用枚举名和"."运算符来获取枚举类型中的常量。例如:x = Season.spring
6、注释
Java支持三种注释方式:
- 单行注释:以双斜杠"//"标识,只能注释一行内容,用在注释信息较少的是偶。
- 多行注释:以"/*“标识开头,”*/"标识结尾的注释方式,能注释多行内容,
- 文档注释:以"/**“标识开头,”*/"标识结尾的注释方式,一般用在类、方法和变量上面,用来描述其作用。
三、Java运算符及优先级
1、算术运算符:
算符运算符:
- +、-、*、/、%、++、–
2、赋值运算符
赋值运算符:
- 格式:变量=表达式;
- 复合赋值运算法:+=、-=、*=、/=、%=
3、关系运算符
关系运算法:属于二目运算符,用来比较两个值的关系,结果是boolean型,当运算符对应的关系成立时,运算结果是true、否者false。
- >、<、>=、<=、==、!=
4、逻辑运算符
逻辑运算法:
- 逻辑与:&&
- 逻辑或:||
- 逻辑非:!
注意:其中&&、||属于短路运算、也就是如果第一个表达式能决定最终结果则不进行后面的计算。
5、位运算符
位运算法:两个整型数据实施位运算,即对两个整型数据对应的位进行运算得到一个新的整型数据
- 按位与:&
- 按位或:|
- 按位非:~
- 按位异或:^
6、其他运算法
instanceof运算符:instanceof运算符是一个二目运算符,左边的操作元是一个对象,右边是一个类,当左边的对象和右边的类或子类创建的对象时,该运算符运算的结果是true。
7、运算符优先级
Java中的运算符优先级从高到低排序(实际工作用的较少,运算顺序主要用括号控制)
- 圆括号:()
- 逻辑非、自增、自减:!、++、–
- 乘法、除法、取余:*、/、%
- 加法、减法:+、-
- 小于、小于等于、大于、大于等于:<、<=、>、>=
- 等于、不等于:==、!=
- 逻辑与:&&
- 逻辑或:||
- 赋值运算:=、+=、-=、*=、/=、%=
四、Java流程控制
1、条件语句
简单if语句
语法格式:
if(条件){
条件成立时执行的代码
}
示例:
int age= 99;
if(age < 18){
System.out.println("未成年!");
}
简单if-else语句
if-else语句的操作比if语句多了一步;当条件成立时执行if部分的代码块,条件不成立时则进入else部分。
语法格式:
if(条件){
条件成立时执行的代码块
}else{
条件不成立时执行的代码块
}
示例:
int age= 99;
if(age < 18){
System.out.println("未成年人!");
}else{
System.out.println("成年人!");
}
多重if-else语句
多重if-else语句,当条件1不成立的情况下才会进入条件2进行判断,当前面的条件均不成立时才会执行else块内的代码。
语法格式:
if(条件1){
条件1成立时执行的代码块
}else if(条件2){
条件2成立时执行的代码块
}else{
条件1,2均不成立时执行的代码块
}
示例:
int age= 99;
if(age < 0){
System.out.println("输入的年龄有误");
}else if(age < 18)
System.out.println("未成年人!");
else{
System.out.println("成年人!");
}
switch-case语句
有时候可能需要对变量进行等值判断,则可以使用switch-case语句
语法格式:
switch(表达式){
case 值1:
执行代码块1
break;
case 值2:
执行代码块2
break;
case 值2:
执行代码块3
break;
default:
默认执行代码块
}
示例:
int age= 99;
switch(age){
case 18:
System.out.println("今年18岁");
break;
case 20:
System.out.println("今年20岁");
break;
case 22:
System.out.println("今年22岁");
break;
default:
System.out.println("??????");
}
2、循环语句
Java中常用的3种循环语句:while、do-while、for,循环语句可以重用代码使代码更精简,并且可读性好,更利于维护。
while语句
语法格式:
while(判断条件){
循环操作
}
执行流程:
- 1.先判断while后面的循环条件是否成立(真/假)。
- 2.当循环条件成立时,执行循环内的代码,然后重复执行1、2直到循环条件不成立为止。
do-while语句
语法格式:
do{
循环操作
}while(判断条件);
执行流程:
- 1.先执行一遍循环操作,然后判断循环条件是否成立(真/假)
- 2.如果循环条件成立,继续执行1、2,直到循环条件不成立为止。
for语句
语法格式:
for(循环变量初始化; 循环条件; 更新循环变量){
循环操作
}
执行流程:
- 1.初始化循环变量
- 2.判断循环条件是否成立(真/假)
- 3.当循环条件成立时,执行循环内的操作
- 4.更新循环变量
- 5.重复2、3、4,直到循环条件不成立为止。
注意:for循环后面括号中的三个表达式必须用";“分号隔开,三个表达式都可以省略但”;"分号不能省略。
增强for循环 foreach语句
foreach一般适用于对集合或数组的遍历,并且在循环遍历过程中不能对遍历对象进行修改(添加删除操作),如果想要修改则使用for循环。
语法格式:
for(元素类型 元素名称:遍历数组(集合)){
循环操作
}
示例:
List<String> arr = new ArrayList<String>();
arr.add("元素1");
arr.add("元素2");
arr.add("元素3");
for(String str: arr){
System.out.println(str);
}
break与continue语句
如果想主动退出循环可以使用break或continue语句
- break语句用于跳出整个循环语句
- continue语句主要用于跳过本次循环,执行下次循环。
五、数组(实际工作中常用List)
1、一维数组
数组是一组相同数据类型变量的集合,数组中的元素在内存中以连续存储的方法进行存储,数组的下标都是从0开始的。
数组的创建和初始化
数组的作用
- 存储相同数据类型的一组数据
- 对同类型数据集中存储、管理、便于遍历
数组的创建
方式一:声明
格式:
数组类型 数组名称[];
- 示例:int scores[];
数组类型[] 数组名称;
- 示例:int[] scores;
注意:声明数组时可以不设置数组长度。
方式二:分配空间
格式:
数据类型 数组名称[] = new 数组类型[数组长度];
- 示例:
- int scores[] = new int[10];
- String[] names = new String[10];
注意:数组元素根据类型不同,有不同的初始值
- int 类型,默认初始值为0
- String类型,默认初始值为null
- double类型,默认初始值为0.0
数组的赋值
方式一:先声明,再赋值(手动录入或动态从键盘录入)
int scores[] = new int[10];
scores[0] = 1;
scores[1] = 2;
方式二:声明并赋值
int scores[] = {88,99,77,66,55};
int scores[] = new int[10]{88,77,66...};
数组的遍历
方式一:使用for循环
int scores[] = {11,22,33,44,55};
for(int i=0;i<scores.length;i++){
System.out.println(scores[i]);
}
方式二:使用foreach循环
int scores[] = {11,22,33,44,55};
for(int score: scores){
System.out.println(score);
}
数组的简单排序
Arrays类方法排序
Arrays类是Java中提供的一个工具类,在java.util包中,该类包含了一些方法用来直接操作数组,可实现数组的排序、搜索等。
语法:Arrays.sort(数组名); //按升序进行排序
已知一个数组int[] num={32,66,55,45,87,83,74,95,99},现在从小到大进行排序
int[] nums={32,66,55,45,87,83,74,95,99};
Arrays.sort(nums); //升序排序
for(int i=0;i<nums.length;i++){
System.out.println(nums[i]);
}
数组元素的查找
已知一个数组int[] nums={32,66,55,45,87,83,74,95,99},请找出数组中有无95这个数,有则输出数组下标
方法一:线性查找法
在给定的值中进行搜索,从一端开始逐个检查每个元素,直到找到所需元素的过程。
int[] nums={32,66,55,45,87,83,74,95,99};
int index=-1;
for(int i=0;i<nums.length;i++){
if(nums[i] == 95){
index = i;
System.out.println("值:"+nums[i]+" 下标:"+index);
}
}
方法二:二分查找法
将数组先排序,在通过将数组中间位置的元素与查找关键字对比,如果两者相等则查找完成,否则利用中间位置将数组分为前、后两个子数组,如果中间位置的值大于查找关键字则进一步查找前子数组,否则进一步查找后子数组。重复以上过程,直到找到或找不到为止。
// 先排序,升序
Arrays.sort(nums);
for (int i = 0;i<nums.length;i++){
System.out.println("值:"+nums[i]+" 下标:"+i);
}
// 再查找
int index = -1;
int start = 0;
int end = nums.length-1;
int middle = 0;
do {
middle = (start+end)/2;
if(nums[middle] == 95){
index = middle;
System.out.println("找到 值:"+nums[index]+" 下标:"+index);
break;
}
if(nums[middle] < 95){
start = middle + 1;
}else {
end = middle - 1;
}
}while (start <= end);
2、二维数组
二维数组可以看成是以数组为元素的数组,Java中二维数组的声明和初始化应按照从高维到低维的顺序进行。
例如:
int[][] arr1 = new int[10][]; //一维长度未定
int[][] arr2 = new int[10][20];//一维、二维长度都确定
二数组创建并分配空间
格式:
方式一:
数组类型[][] 数组名 = new 数据类型[二维长度][一维长度]
方式二:
数组类型[][] 数组名;
数组名 = new 数据类型[二维长度][一维长度]
二维数组的赋值
二维数组的赋值和一维数组类似,可以通过下标来逐个赋值,注意数组索引从0开始。
格式:
数组名[二维长度][一维长度] = 值;
int[][] arr1 = new int[][]{{1,2,3},{3,2,1}};
arr1[0][0] = 6;
二维数组的遍历
二维数组的访问和输出同一维数组一样,只是多了一个下标而已。在遍历时需要再内嵌一个循环。
for (int i=0;i<arr1.length;i++){
for (int j=0;j<arr1[i].length;j++){
System.out.println("值:"+arr1[i][j]);
}
}
六、方法
1、什么是方法
Java方法是语句的集合,它们组合在一起完成一个功能。
2、方法的优点
方法的优点
- 方法可以使得程序变得更简短而清晰。
- 方法可以有利于程序的阅读维护。
- 方法提高了代码的重用性。
- 方法提高程序开发的效率。
3、方法的命名规则
一般方法的名字第一个字母应以小写字母作为开头,后面的单词则使用大写字母开头。例如:getName
4、方法的定义
方法的定义格式:
修饰符 返回值类型 方法名(参数类型 参数名[,参数类型 参数名...]){
...// 方法体
...// 返回值
}
5、方法的调用
当程序调用一个方法时,程序的控制权则交给了被调用的方法。当被调方法的返回语句执行完成后控制权交还给调用程序。
Java根据方法的返回值支持两种调用方式。
方式一:当方法返回一个值的时候,方法通常被当做一个值。
示例:
int a = max(30,40);
方式二:当方法没有返回值或返回值为void时,则方法的调用可以当做一条语句。
示例:
System.out.println("你好,世界");