java语法(上)
1. src下的Main.java文件名和类名要一样,大小写也要一样 ;Main.java文件中允许定义多个私有类(不加Public),只能定义一个Public公共类并且只能是Main类。 如下:

2.注释-- 多行注释 与单行注释
/* class Pig { public static void SayHello() { //System.out.println("Hello"); } } */
3.数据类型
String name="root"; int age=18; //常量 final int age=18 //变量名大小写规范 在py中变量名如:frist_name, 而在java中首字母是小写 String fristName="root"
整数类型包括:
byte 字节, 【1个字节】表示范围 -128~127
short 短整型, 【2个字节】表示范围 -32768~32767
int 整型,【4个字节】表示范围 -2147483648 ~ 2147483647
long类型,【8个字节】表示范围 -9223372036854775808~ 9223372036854775807
字符类型
---char 类型, 定义char变量类型如 :char v1='自'
---String类型 ,最常见的字符串定义是v1和v2。
---v4是放的utf-8的字节数组,对应的变量值也是武沛齐。
---v5是放的GBK的字节数组,对应的变量值也是武沛齐。
---v6是放的一个char类型数组,对应的变量值也是武沛齐。

---StringBuilder类型,用于字符串拼接,用sb.append("xxx")追加; 用sb.toString() 组成拼接好的字符串
---StringBuffer类型,用于在多线程中字符串拼接,内部会加锁
4.输入和输出 (其中System.in是读取屏幕上的输入流,nextLine()方法是读取一行,其中printIn()方法是换行)

5. if 与swith的语法与C#一样
6. while,do while循环的语法与C#一样
7. for循环的语法与C#一样
8.数组定义
数组在实例化时,初始数组中的个数后,长度是不能变的,不能删除和新增,只能修改,数组是一个固定容器
---String[] 字符串数组
String[] nameList={"张三","李四"};
int len=nameList.length;
---int[] int数组
//初始化后默认数组中的值为[0,0,0] int[] numArray=new int[3]; //相当于是修改第一个值 numArray[0]=123; //output:[123, 0, 0] System.out.println(Arrays.toString(numArray));
在python中列表是动态变化的,底层实现是基于C语言数组实现(固定长度), 之所以可以动态变化,是因为python内部做了扩容和迁移
9. byte字节
通过在python和java中定义字符串,都转成10时制, 由于java与python的字节范围表示不一样。
---所以在python中当10进制有负数时,如第一个为 -26, 如果+256 就与java中第一个230十进制一样了。

10.Object类
java中所有类都继承Object类(是所有类的父类)
//由于Object是父类,所以都可以做父类接着 Object name=new String("自动化"); Object v1=123; //可以在转回来 String name2=(String)name;
11.List系列
java中List是一个接口,用于约束实现List接口的类。如ArrayList、LinkedList都实现了List接口类, LinkedList是队列类型
//add时可以放任意类型,理解为Object类型ArrayList<Object> v1=new ArrayList<Object>() ArrayList v1=new ArrayList(); v1.add("自动化"); v1.add(123); v1.add(true); //add时放指定类型 ArrayList<String> v2=new ArrayList<String>(); v2.add("自动化"); //获取集合中指定索引值, 存入都是Object类型,取出来要转换 String s=(String)v1.get(0); //set是修改索引对应的值,该索引下标必须存在 v1.set(0,"自动化修改"); //集合大小 v1.size(); //包含 v1.contains("自动"); //删除 v1.remove("自动化修改"); v1.remove(1);
//迭代器输出 Iterator it= v2.iterator(); while(it.hasNext()){ String item= (String)it.next(); }
12.set
set也是一个接口,常见实现这个接口有两个类,用于实现不重复的多元素集合
---HashSet 有去重和无序
---TreeSet 有去重,内部默认排序(ascii、unicode)[不同的数据类型,无法进行比较]
//可以放任意类型 HashSet s1=new HashSet(); s1.add(123); s1.add(true); s1.add("张三"); //放指定的类型 HashSet<String> s2=new HashSet<String> (); s2.add("张三"); s2.add("李四"); HashSet<String> s3=new HashSet<String> (); s3.addAll(s1); //自动去重output [张三, 123, true] System.out.println(s3); //只取集合中的差集 s3.removeAll(s2); //output [123, true] System.out.println(s3); //只取集合中的交集 s3.retainAll(s2); //output [张三] , System.out.println(s3);
TreeSet<String> ts=new TreeSet<String>(); ts.add("p站"); ts.add("b站"); ts.add("a站"); //除了用迭代器,还可以用for循环取出集合中的元素,去重排序后依次输出为a站、b站、p站 for(String o:ts){ System.out.println(o); }
13. Map系列
在逆向中比较常见的,对应的就是python中的字典,Map是一个接口,常见实现这个接口的有两个类,用于存储键值对。
--HashMap 无序
--TreeMap 默认是根据key排序的 常用unicode 排序
HashMap<String,Integer> hm=new HashMap<String, Integer>(); hm.put("张三",18); hm.put("李四",20); hm.put("王五",30); //output {李四=20, 张三=18} System.out.println(hm); //删除 hm.remove("张三"); //根据key获取值 Object o= hm.get("张三"); //判断key和值 是否存在 boolean existKey= hm.containsKey("张三"); boolean existValue= hm.containsValue(18); //根据key 修改值 hm.replace("张三",30); //循环读取 entrySet读出来格式为[李四=20, 王五=30] for(Map.Entry<String,Integer> entry : hm.entrySet()) { String k = entry.getKey(); int v = entry.getValue(); System.out.println(k+":"+v); }
注意,在逆向后,如果代码中出现了TreeMap 添加许多键值,循环输出拼接成字符串如: "张三=18&李四=20" ,再md5后得到如:sflksfdflksdfjlsdfjsdffj。如果了解这段加密代码,在用python来实现时,会发现md5的值怎么都不正确,这是因为TreeMap在循环输出时已排序好了,而python输出拼接成字符串时不会排序,可能拼接如:"李四=20&张三=18",所以md5的值不对。
info={ "aid":"234231", "cid":"sdfdse", "bulid" :"1233" } #如果要实现java中的TreeMap自动排序,需要如下 result="&".join(["{}={}".format(key,info[key]) for key in sorted(info.keys())])
14. 对象与重载
重载在逆向中意义何在, 后面学习了Hook技术后会用得到。
---如果手机上运行得物app,点击登录:login-->send_request,这时自己可以重载一个send_request方法,让hook执行我们重载的这个方法。
#重载 public void F1() { } public void F1(int age) { } public void F1(int age,String name) { }
15.继承
继承用extends。逆向时要注意重载和继承,要知道实例化对象到底是谁(父类可以泛指子类对象),调用的方法是属于谁的实例。
到底是谁:
--hook机制, console.log(obj.getClass()) 这样输出知道是哪个包,哪个类。
--根据调用栈向上寻找
class Person{ public void Say() { System.out.println("hello"); } } class Student extends Person{ public void Say() { System.out.println("hello student"); } }
16.接口
实现接口用implements。在逆向时,例如接口名当参数传递时,要知道对象到底是谁?
public void Run(IMessage message){ message.getInfo(); }
--搜索接口名字 IMessage --》implements IMessage 或者搜索 new IMessage
--搜索方法名 getInfo --》定义方法
--hook run方法 (假设Run方法是属于Base类) 下面是实现hook,这样知道了message是属于哪个类
Base.Run=function(message){
console.log(message)
}
下面是接口实现的常用代码
interface IInfo{ void GetInfo(); } interface IMessage{ void GetMessage(); } class Info implements IMessage,IInfo{ public void GetInfo(){ System.out.println("hello"); } public void GetMessage(){ System.out.println("hello"); } }
17.抽象
abstract class Base { public void F1(){ } public abstract void F2(String str); } class OKhttp extends Base { @Override public void F2(String str) { } }
18. 包与修饰符

包可以理解为一个文件夹,作用域,如使用import utils.Helper导入。
类的修饰符有:public 和默认的default。 默认修饰符创建的类只能被当前包中的其它类调用。
---如:Helper类是默认修饰符,Db.java类中可以调用Helper类。但是Hello.java类中不可调用Helper类。
方法和属性的修饰符有:
--public 公共的
--privte 私有的,只允许自己类调用
--protected 受保护的,同一个包或子类可以访问(即使没有在一个包内,也可以访问父类中受保护成员)
--default 默认的,只能在同一个包内访问
浙公网安备 33010602011771号