Android逆向-003.Java基础入门

一、初识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(表达式){
	case1:
		执行代码块1
		break;
	case2:
		执行代码块2
		break;
	case2:
		执行代码块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("你好,世界");

版权声明:本文为weixin_46734340原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。