首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

2017深圳云栖TechInsight活动回顾:动手实验室-从零搭建一个金融级分布式交易系统

作为一次面向开发者的体验活动,我们力求使蚂蚁金服的核心金融技术和产品变得触手可及。旨在通过动手实验室课程,围绕分布式数据库OceanBase、蚂蚁分布式中间件、移动平台mPaaS、零号云客服等产品,实现一个金融场景下移动转账交易的示例解决方案。我们为此构建了一套完整的示例项目和实验手册,涵盖从关键组件说明、应用开发到部署的全方位体验流程。在TechInsight的第一天下午,通过讲师对知识点的互动分享和代码实现实操演示,使开发者能够直观地体验到相关云产品的快速入门和最佳实践。 关于创新金融分论坛的分享内容回顾,请见2017深圳云栖TechInsight活动回顾:创新金融。 Workshop课程回顾 1. OceanBase运维管理后台体验 李凌云(云琚) & 俞仁杰(首仁) 「云数据库 OceanBase」- 演示和体验分布式云数据

优秀的个人博客,低调大师

鸿蒙内核源码分析(用栈方式篇) | 栈是构建底层运行的基础 | 中文注解HarmonyOS源码 | v20.03

鸿蒙内核源码注释中文版 < Gitee仓 | CSDN仓 | Github仓 | Coding仓 >精读内核源码,中文注解分析,深挖地基工程,构建底层网图,四大码仓每日同步更新 鸿蒙源码分析系列篇 < CSDN | OSCHINA | WeHarmony | 公众号 >问答式导读,生活式比喻,表格化说明,图形化展示,主流站点每日同步更新 精读内核源码就绕不过汇编语言,鸿蒙内核有6个汇编文件,读不懂它们就真的很难理解以下问题. 1.系统调用是如何实现的? 2.CPU是如何切换任务和进程上下文的? 3.硬件中断是如何处理的? 4.main函数到底是怎么来的? 5.开机最开始发生了什么? 6.关机最后的最后又发生了什么? 以下是一个很简单的C文件编译成汇编代码后的注解.读懂这些注解会发现汇编很可爱,甚至还会上瘾,并没有想象中的那么恐怖,读懂它会颠覆你对汇编和栈的认知. #include <stdio.h> #include <math.h> int square(int a,int b){ return a*b; } int fp(int b) { int a = 1; return square(a+b,a+b); } int main() { int sum = 1; for(int a = 0;a < 100; a++){ sum = sum + fp(a); } return sum; } //编译器: armv7-a clang (trunk) square(int, int): sub sp, sp, #8 @sp减去8,意思为给square分配栈空间,只用2个栈空间完成计算 str r0, [sp, #4] @第一个参数入栈 str r1, [sp] @第二个参数入栈 ldr r1, [sp, #4] @取出第一个参数给r1 ldr r2, [sp] @取出第二个参数给r2 mul r0, r1, r2 @执行a*b给R0,返回值的工作一直是交给R0的 add sp, sp, #8 @函数执行完了,要释放申请的栈空间 bx lr @子程序返回,等同于mov pc,lr,即跳到调用处 fp(int): push {r11, lr} @r11(fp)/lr入栈,保存调用者main的位置 mov r11, sp @r11用于保存sp值,函数栈开始位置 sub sp, sp, #8 @sp减去8,意思为给fp分配栈空间,只用2个栈空间完成计算 str r0, [sp, #4] @先保存参数值,放在SP+4,此时r0中存放的是参数 mov r0, #1 @r0=1 str r0, [sp] @再把1也保存在SP的位置 ldr r0, [sp] @把SP的值给R0 ldr r1, [sp, #4] @把SP+4的值给R1 add r1, r0, r1 @执行r1=a+b mov r0, r1 @r0=r1,用r0,r1传参 bl square(int, int)@先mov lr, pc 再mov pc square(int, int) mov sp, r11 @函数执行完了,要释放申请的栈空间 pop {r11, lr} @弹出r11和lr,lr是专用标签,弹出就自动复制给lr寄存器 bx lr @子程序返回,等同于mov pc,lr,即跳到调用处 main: push {r11, lr} @r11(fp)/lr入栈,保存调用者的位置 mov r11, sp @r11用于保存sp值,函数栈开始位置 sub sp, sp, #16 @sp减去8,意思为给main分配栈空间,只用2个栈空间完成计算 mov r0, #0 @初始化r0 str r0, [r11, #-4] @作用是保存SUM的初始值 str r0, [sp, #8] @sum将始终占用SP+8的位置 str r0, [sp, #4] @a将始终占用SP+4的位置 b .LBB1_1 @跳到循环开始位置 .LBB1_1: @循环开始位置入口 ldr r0, [sp, #4] @取出a的值给r0 cmp r0, #99 @跟99比较 bgt .LBB1_4 @大于99,跳出循环 mov pc .LBB1_4 b .LBB1_2 @继续循环,直接 mov pc .LBB1_2 .LBB1_2: @符合循环条件入口 ldr r0, [sp, #8] @取出sum的值给r0,sp+8用于写SUM的值 str r0, [sp] @先保存SUM的值,SP的位置用于读SUM值 ldr r0, [sp, #4] @r0用于传参,取出A的值给r0作为fp的参数 bl fp(int) @先mov lr, pc再mov pc fp(int) mov r1, r0 @fp的返回值为r0,保存到r1 ldr r0, [sp] @取出SUM的值 add r0, r0, r1 @计算新sum的值,由R0保存 str r0, [sp, #8] @将新sum保存到SP+8的位置 b .LBB1_3 @无条件跳转,直接 mov pc .LBB1_3 .LBB1_3: @完成a++操作入口 ldr r0, [sp, #4] @SP+4中记录是a的值,赋给r0 add r0, r0, #1 @r0增加1 str r0, [sp, #4] @把新的a值放回SP+4里去 b .LBB1_1 @跳转到比较 a < 100 处 .LBB1_4: @循环结束入口 ldr r0, [sp, #8] @最后SUM的结果给R0,返回值的工作一直是交给R0的 mov sp, r11 @函数执行完了,要释放申请的栈空间 pop {r11, lr} @弹出r11和lr,lr是专用标签,弹出就自动复制给lr寄存器 bx lr @子程序返回,跳转到lr处等同于 MOV PC, LR 这个简单的汇编并不是鸿蒙的汇编,只是先打个底,由浅入深, 但看懂了它基本理解鸿蒙汇编代码没有问题, 后续将详细分析鸿蒙内核各个汇编文件的作用. 开始分析上面的汇编代码. 第一: 上面的代码和鸿蒙内核用栈方式一样,都采用了递减满栈的方式, 什么是递减满栈? 递减指的是栈底地址高于栈顶地址,满栈指的是SP指针永远在栈顶.一定要理解递减满栈,否则读不懂内核汇编代码.举例说明: square(int, int): sub sp, sp, #8 @sp减去8,意思为给square分配栈空间,只用2个栈空间完成计算 str r0, [sp, #4] @第一个参数入栈 str r1, [sp] @第二个参数入栈 ldr r1, [sp, #4] @取出第一个参数给r1 ldr r2, [sp] @取出第二个参数给r2 mul r0, r1, r2 @执行a*b给R0,返回值的工作一直是交给R0的 add sp, sp, #8 @函数执行完了,要释放申请的栈空间 bx lr @子程序返回,等同于mov pc,lr,即跳到调用处 首句汇编的含义就是申请栈空间, sp = sp - 8 ,一个栈内单元(栈空间)占4个字节,申请2个栈空间搞定函数的计算,仔细看下代码除了在函数的末尾 sp = sp + 8 又恢复在之前的位置的中间过程,SP的值是没有任务变化,它的指向是不动的, 这跟很多人对栈的认知是不一样的,它只是被用于计算,例如 ldr r1, [sp, #4] 的意思是取出SP+4这个虚拟地址的值给r1寄存器,SP的值并没有改变的,为什么要+呢,因为SP是指向栈顶的,地址是最小的. 满栈就是用栈过程中对地址的操作不能超过SP,所以你很少在计算过程中看到 把sp-4地址中的值给某个寄存器, 除非是特别的指令,否则不可能有这样的指令. 第二: sub sp, sp, #8 和 add sp, sp, #8 是成对出现的,这就跟申请内存,释放内存的道理一样,这是内核对任务的运行栈管理方式,一样用多少申请多少,用完释放.空间大小就是栈帧,这是栈帧的本质含义. 第三: push {r11, lr} 和 pop {r11, lr} 也是成对出现的,主要是用于函数调用,例如 A -> B, B要保存A的栈帧范围和指令位置, lr保存是是A函数执行到哪个指令的位置, r11干了fp的工作,其实就是指向 A的栈顶位置,如此B执行完后return回A的时候,先mov pc,lr 内核就知道改执行A的哪条指令了,同时又知道了A的栈顶位置. 第四: 频繁出现的R0寄存器的作用用于传参和返回值, A调用B之前,假如有两个参数,就把参数给r0 ,r1记录,充当了A的变量, 到了B中后,先让 r0,r1入栈,目的是保存参数值, 因为 B中要用r0,r1 ,他们变成B的变量用了. 返回值都是默认统一给r0保存. B中将返回值给r0,回到A中取出R0值对A来说这就是B的返回值. 这是以上为汇编代码的分析,追问两个问题 第一:如果是可变参数怎么办? 100个参数怎么整, 通过寄存器总共就12个,不够传参啊 第二:返回值可以有多个吗? 请在评论区留言 喜欢就点赞+关注下吧 8-) 您的关注真的很重要 :) 作者邮箱:weharmony@126.com 鸿蒙内核源码注释中文版 < Gitee仓 | CSDN仓 | Github仓 | Coding仓 >精读内核源码,中文注解分析,深挖地基工程,构建底层网图,四大码仓每日同步更新 鸿蒙源码分析系列篇 < CSDN | OSCHINA | WeHarmony | 公众号 >问答式导读,生活式比喻,表格化说明,图形化展示,主流站点每日同步更新

优秀的个人博客,低调大师

java基础学习_集合类02_List的子类、泛型、增强for循环、静态导入、可变参数_day16总结

==========================================================================================================================================================涉及到的知识点有:1:List的子类(掌握) (1)List的子类特点 (2)ArrayList类 (3)Vector类 (4)LinkedList类 (5)案例2:泛型(掌握) (1)泛型的概述 (2)泛型的格式 (3)泛型的好处 (4)泛型的前世今生 (5)我们在哪里使用呢?3:增强for循环(掌握)4:静态导入(了解) (1)静态导入的概述 (2)静态导入的格式 (3)注意事项5:可变参数(掌握) (1)可变参数的概述 (2)可变参数的格式 (3)注意事项 (4)Arrays工具类中的一个方法6:练习(掌握) A:集合的嵌套遍历 B:产生10个1-20之间的随机数,要求随机数不能重复 C:键盘录入多个数据,以0结束,并在控制台输出最大值7:要掌握的代码==========================================================================================================================================================1:List的子类(掌握) (1)List的子类特点 ArrayList: 底层数据结构是数组,查询快,增删慢 线程不安全,效率高 Vector: 底层数据结构是数组,查询快,增删慢 线程安全,效率低 LinkedList: 底层数据结构是链表,查询慢,增删快 线程不安全,效率高 (2)ArrayList类 A:没有特有功能需要学习 B:案例 a:ArrayList存储字符串并遍历 b:ArrayList存储自定义对象并遍历 (3)Vector类 A:有特有功能 a:添加功能 public void addElement(E obj) -- add() b:获取功能 public E elementAt(int index) -- get() public Enumeration<E> elements() -- Iterator iterator() 抽象方法: boolean hasMoreElements() -- hasNext() Object nextElement() -- next() JDK升级的原因: A:提高安全 B:提高效率 C:简化书写 B:案例 a:Vector存储字符串并遍历 b:Vector存储自定义对象并遍历 (4)LinkedList类 A:有特有功能 a:添加功能 public void addFirst(Object e) 在最前面添加 public void addLast(Object e) 在最后面添加(该功能意义不大) b:删除功能 public Object removeFirst() public Object removeLast() c:获取功能 public Object getFirst() public Obejct getLast() B:案例 a:LinkedList存储字符串并遍历 b:LinkedList存储自定义对象并遍历 (5)案例 A:去除集合中的多个字符串的重复元素 如果字符串的内容相同,即为重复元素。 法一: 1 package cn.itcast_04; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 /* 7 * ArrayList去除集合中字符串的重复值(字符串的内容相同) 8 * 9 * 分析: 10 * A:创建集合对象 11 * B:添加多个字符串元素(包含内容相同的) 12 * C:创建新集合 13 * D:遍历旧集合,获取得到每一个元素 14 * E:拿这个元素到新集合去找,看有没有 15 * 有:不搭理它 16 * 没有:就添加到新集合 17 * F:遍历新集合 18 */ 19 public class ArrayListDemo { 20 public static void main(String[] args) { 21 // 创建集合对象 22 ArrayList array = new ArrayList(); 23 24 // 添加多个字符串元素(包含内容相同的) 25 array.add("hello"); 26 array.add("world"); 27 array.add("java"); 28 array.add("world"); 29 array.add("java"); 30 array.add("world"); 31 array.add("world"); 32 array.add("world"); 33 array.add("world"); 34 array.add("java"); 35 array.add("world"); 36 37 // 创建新集合 38 ArrayList newArray = new ArrayList(); 39 40 // 遍历旧集合,获取得到每一个元素 41 Iterator it = array.iterator(); 42 while (it.hasNext()) { 43 String s = (String) it.next(); 44 45 // 拿这个元素到新集合去找,看有没有 46 if (!newArray.contains(s)) { 47 newArray.add(s); 48 } 49 } 50 51 // 遍历新集合 52 for (int x = 0; x < newArray.size(); x++) { 53 String s = (String) newArray.get(x); 54 System.out.println(s); 55 } 56 } 57 58 } ArrayListDemo.java 法二(不常用): 1 package cn.itcast_04; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 /* 7 * 需求:ArrayList去除集合中字符串的重复值(字符串的内容相同) 8 * 要求:不能创建新的集合,就在以前的集合上做。 9 */ 10 public class ArrayListDemo2 { 11 public static void main(String[] args) { 12 // 创建集合对象 13 ArrayList array = new ArrayList(); 14 15 // 添加多个字符串元素(包含内容相同的) 16 array.add("hello"); 17 array.add("world"); 18 array.add("java"); 19 array.add("world"); 20 array.add("java"); 21 array.add("world"); 22 array.add("world"); 23 array.add("world"); 24 array.add("world"); 25 array.add("java"); 26 array.add("world"); 27 28 // 由选择排序思想引入,我们就可以通过这种思想做这个题目 29 // 拿0索引的依次和后面的比较,有就把后的干掉 30 // 同理,拿1索引... 31 // 因为ArrayList底层数据结构是数组,而数组查询快,增删慢 32 for (int x = 0; x < array.size() - 1; x++) { 33 for (int y = x + 1; y < array.size(); y++) { 34 if (array.get(x).equals(array.get(y))) { 35 array.remove(y); // 因为你删一个的同时,剩下的数组会挤上去一个,而挤上的这一个没有判断 36 y--; // 所以我要再回去比较一下 37 } 38 } 39 } 40 41 // 遍历集合 42 Iterator it = array.iterator(); 43 while (it.hasNext()) { 44 String s = (String) it.next(); 45 System.out.println(s); 46 } 47 } 48 } ArrayListDemo2.java B:去除集合中的多个自定义对象的重复元素 如果自定义对象的成员变量值都相同,即为重复元素。 1 package cn.itcast_04; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 /* 7 * 需求:去除集合中自定义对象的重复值(对象的成员变量值都相同) 8 * 9 * 我们按照和字符串一样的操作,发现出问题了。 10 * 为什么呢? 11 * 我们必须思考哪里会出问题? 12 * 通过简单的分析,我们知道问题出现在了判断上。 13 * 而这个判断功能是集合自己提供的,所以我们如果想很清楚的知道它是如何判断的,就应该去看源码。 14 * contains()方法的底层依赖的是equals()方法。 15 * 而我们的学生类中没有equals()方法,这个时候,默认使用的是它父亲Object的equals()方法。 16 * Object()的equals()默认比较的是地址值,所以,它们进去了。因为new的东西,地址值都不同。 17 * 按照我们自己的需求,比较成员变量的值,重写equals()即可。 18 * 自动生成即可。 19 */ 20 public class ArrayListDemo3 { 21 public static void main(String[] args) { 22 // 创建集合对象 23 ArrayList array = new ArrayList(); 24 25 // 创建学生对象 26 Student s1 = new Student("林青霞", 27); 27 Student s2 = new Student("林志玲", 40); 28 Student s3 = new Student("凤姐", 35); 29 Student s4 = new Student("芙蓉姐姐", 18); 30 Student s5 = new Student("翠花", 16); 31 Student s6 = new Student("林青霞", 27); 32 Student s7 = new Student("林青霞", 18); 33 34 // 添加元素到集合 35 array.add(s1); 36 array.add(s2); 37 array.add(s3); 38 array.add(s4); 39 array.add(s5); 40 array.add(s6); 41 array.add(s7); 42 43 // 创建新集合 44 ArrayList newArray = new ArrayList(); 45 46 // 遍历旧集合,获取得到每一个元素 47 Iterator it = array.iterator(); 48 while (it.hasNext()) { 49 Student s = (Student) it.next(); 50 51 // 拿这个元素到新集合去找,看有没有 52 if (!newArray.contains(s)) { 53 newArray.add(s); 54 } 55 } 56 57 // 遍历新集合 58 for (int x = 0; x < newArray.size(); x++) { 59 Student s = (Student) newArray.get(x); 60 System.out.println(s.getName() + "---" + s.getAge()); 61 } 62 } 63 } ArrayListDemo3.java 1 package cn.itcast_04; 2 3 public class Student { 4 private String name; 5 private int age; 6 7 public Student() { 8 super(); 9 } 10 11 public Student(String name, int age) { 12 super(); 13 this.name = name; 14 this.age = age; 15 } 16 17 public String getName() { 18 return name; 19 } 20 21 public void setName(String name) { 22 this.name = name; 23 } 24 25 public int getAge() { 26 return age; 27 } 28 29 public void setAge(int age) { 30 this.age = age; 31 } 32 33 @Override 34 public boolean equals(Object obj) { 35 if (this == obj) 36 return true; 37 if (obj == null) 38 return false; 39 if (getClass() != obj.getClass()) 40 return false; 41 Student other = (Student) obj; 42 if (age != other.age) 43 return false; 44 if (name == null) { 45 if (other.name != null) 46 return false; 47 } else if (!name.equals(other.name)) 48 return false; 49 return true; 50 } 51 52 } Student.java C:用LinkedList模拟一个栈数据结构的集合类,并测试。 你要定义一个集合类,只不过内部可以使用LinkedList来实现(模拟)。 这样做的好处是:我们用自己的方法,让外界不知道我们用的是谁. package cn.itcast_05; import java.util.LinkedList; /** * 自定义的栈集合 * * @author 风清扬 * @version V1.0 */ public class MyStack { private LinkedList link; public MyStack() { link = new LinkedList(); } public void add(Object obj) { link.addFirst(obj); } public Object get() { // return link.getFirst(); return link.removeFirst(); // 移除第一个元素并返回被移除的元素,其余的元素自动向上挤 } public boolean isEmpty() { return link.isEmpty(); } } package cn.itcast_05; /* * MyStack的测试 */ public class MyStackDemo { public static void main(String[] args) { // 创建集合对象 MyStack ms = new MyStack(); // 添加元素,底层调用的是addFirst(obj); ms.add("hello"); // 第一个进来,压栈,最里面 ms.add("world"); // 第二个进来,压栈 ms.add("java"); // 第三个进来,压栈 // 改进前 // 改进后 // System.out.println(ms.get()); // java java // System.out.println(ms.get()); // java world // System.out.println(ms.get()); // java hello // NoSuchElementException // System.out.println(ms.get()); 异常 while (!ms.isEmpty()) { System.out.println(ms.get()); } } } -----------------------------------------------------------------------------2:泛型(掌握) (1)泛型的概述 是一种 把明确类型的工作推迟到创建对象或者调用方法的时候才去明确的 特殊的类型。也叫参数化类型,把类型当作参数一样进行传递。 (2)泛型的格式 <数据类型> 注意:该数据类型只能是引用类型。 (3)泛型的好处 A:把运行时期的问题提前到了编译期间 B:避免了强制类型转换 C:优化了程序设计,解决了黄色警告线问题,让程序更安全 (4)泛型的前世今生 A:泛型的由来 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,向上转型是没有任何问题的,但是在向下转型的时候其实隐含了类型转换的问题。 也就存在这隐患,所以Java在JDK1.5以后就提供了泛型来解决这个安全问题,提高程序的安全性。 B:泛型类 把泛型定义在类上 格式:public class 类名<泛型类型1, 泛型类型2, ...> 注意:泛型类型必须是引用数据类型。因为仅仅表示一个参数,所以符合我们命名的标识符规则就行。 public class ObjectTool<T> {...} C:泛型方法 把泛型定义在方法上 格式:public <泛型类型> 返回类型 方法名(泛型类型 泛型名) 注意:方法能接收任意类型的参数 public <T> void show(T t) {...} D:泛型接口 把泛型定义在接口上 格式:public interface 接口名<泛型类型1, 泛型类型2, ...> 注意:把泛型定义在接口上,该接口的实现类是实现的那一刻就知道类型的(不常见),还是以后用的时候才知道类型的(常见)。 public class InterImpl<T> implements Inter<T> {...} E:泛型高级通配符 ? 任意类型,如果没有明确,那么就是Object以及任意的Java类了(泛型如果明确地写的时候,前后必须一致) ? extends E 向下限定,E及其子类 ? super E 向上限定,E及其父类 1 package cn.itcast_07; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 6 /* 7 * 泛型高级(通配符) 8 * ? 任意类型,如果没有明确,那么就是Object以及任意的Java类了 9 * ? extends E 向下限定,E及其子类 10 * ? super E 向上限定,E及其父类 11 */ 12 public class GenericDemo { 13 public static void main(String[] args) { 14 // 泛型如果明确地写的时候,前后必须一致 15 Collection<Object> c1 = new ArrayList<Object>(); 16 // Collection<Object> c2 = new ArrayList<Animal>(); // 编译报错 17 // Collection<Object> c3 = new ArrayList<Dog>(); // 编译报错 18 // Collection<Object> c4 = new ArrayList<Cat>(); // 编译报错 19 20 // ? 任意类型,如果没有明确,那么就是Object以及任意的Java类了 21 Collection<?> c5 = new ArrayList<Object>(); 22 Collection<?> c6 = new ArrayList<Animal>(); 23 Collection<?> c7 = new ArrayList<Dog>(); 24 Collection<?> c8 = new ArrayList<Cat>(); 25 26 // ? extends E 向下限定,E及其子类 27 // Collection<? extends Animal> c9 = new ArrayList<Object>(); // 编译报错 28 Collection<? extends Animal> c10 = new ArrayList<Animal>(); 29 Collection<? extends Animal> c11 = new ArrayList<Dog>(); 30 Collection<? extends Animal> c12 = new ArrayList<Cat>(); 31 32 // ? super E 向上限定,E及其父类 33 Collection<? super Animal> c13 = new ArrayList<Object>(); 34 Collection<? super Animal> c14 = new ArrayList<Animal>(); 35 // Collection<? super Animal> c15 = new ArrayList<Dog>(); // 编译报错 36 // Collection<? super Animal> c16 = new ArrayList<Cat>(); // 编译报错 37 } 38 } 39 40 class Animal { 41 } 42 43 class Dog extends Animal { 44 } 45 46 class Cat extends Animal { 47 } GenericDemo.java (5)我们在哪里使用呢? 看API,如果类、接口、抽象类的后面跟有<E>就说要使用泛型。一般来说就是在集合中使用。 // JDK7的新特性:泛型推断。 // ArrayList<Student> array = new ArrayList<>(); // 但是我不建议这样使用。 ArrayList<Student> array = new ArrayList<Student>();----------------------------------------------------------------------------- 3:增强for循环(掌握) (1)是for循环的一种。增强for是用来替迭代器。 (2)格式 for (元素的数据类型 变量名 : 数组或者Collection集合的对象) { 使用该变量即可,该变量其实就是数组或者集合中的元素。 } (3)好处 简化了数组和集合的遍历。 (4)弊端 增强for循环的目标不能为null。建议在使用前,先判断是否为null。 即:对增强for的目标先进行不为null的判断,然后再使用。 1 package cn.itcast_01; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 /* 7 * JDK5的新特性:自动拆装箱、泛型、增强for、静态导入、可变参数、枚举 8 * 9 * 增强for:是for循环的一种。 10 * 11 * 格式: 12 * for (元素数据类型 变量 : 数组或者Collection集合) { 13 * 使用变量即可,该变量就是元素 14 * } 15 * 16 * 好处:简化了数组和集合的遍历。 17 * 18 * 弊端: 增强for的目标不能为null。 19 * 如何解决呢?对增强for的目标先进行不为null的判断,然后再使用。 20 */ 21 public class ForDemo { 22 public static void main(String[] args) { 23 // 定义一个int数组 24 int[] arr = { 1, 2, 3, 4, 5 }; 25 for (int x = 0; x < arr.length; x++) { 26 System.out.println(arr[x]); 27 } 28 System.out.println("---------------"); 29 // 增强for 30 for (int x : arr) { 31 System.out.println(x); 32 } 33 System.out.println("---------------"); 34 // 定义一个字符串数组 35 String[] strArray = { "林青霞", "风清扬", "东方不败", "刘意" }; 36 // 增强for 37 for (String s : strArray) { 38 System.out.println(s); 39 } 40 System.out.println("---------------"); 41 // 定义一个集合 42 ArrayList<String> array = new ArrayList<String>(); 43 array.add("hello"); 44 array.add("world"); 45 array.add("java"); 46 // 增强for 47 for (String s : array) { 48 System.out.println(s); 49 } 50 System.out.println("---------------"); 51 52 List<String> list = null; 53 // NullPointerException 54 // 这个s是我们从list里面获取出来的,在获取前,它肯定还要做一个判断 55 // 说白了,这就是迭代器的功能 56 if (list != null) { 57 for (String s : list) { 58 System.out.println(s); 59 } 60 } 61 62 // 增强for其实是用来替代迭代器的 63 // ConcurrentModificationException 64 // for (String s : array) { 65 // if ("world".equals(s)) { 66 // array.add("javaee"); 67 // } 68 // } 69 // System.out.println("array:" + array); 70 } 71 } ForDemo.java -----------------------------------------------------------------------------4:静态导入(了解) (1)静态导入的概述 可以直接导入到方法的级别 (2)静态导入的格式 import static 包名....类名.方法名; (3)注意事项 A:被导入的方法必须是静态的 B:如果有多个类下有同名的静态方法,就不好区分了,必须加上前缀才能导入。 所以一般我们并不使用静态导入,但是一定要能够看懂。 1 package cn.itcast_03; 2 3 /* 4 * 可变参数:定义方法的时候不知道该定义多少个参数 5 * 格式: 6 * 修饰符 返回值类型 方法名(数据类型… 变量名){ 7 * 8 * } 9 * 10 * 注意: 11 * 这里的变量其实是一个数组 12 * 如果一个方法有可变参数,并且有多个参数,那么,可变参数的位置肯定是在最后 13 */ 14 public class ArgsDemo { 15 public static void main(String[] args) { 16 // 2个数据求和 17 int a = 10; 18 int b = 20; 19 int result = sum(a, b); 20 System.out.println("result:" + result); // 30 21 22 // 3个数据的求和 23 int c = 30; 24 result = sum(a, b, c); 25 System.out.println("result:" + result); // 60 26 27 // 4个数据的求和 28 int d = 30; 29 result = sum(a, b, c, d); 30 System.out.println("result:" + result); // 90 31 32 // 需求:我要写一个求和的功能,到底是几个数据求和呢,我不太清楚,但是我知道在调用的时候我肯定就知道了。 33 // 为了解决这个问题,Java就提供了一个东西:可变参数 34 result = sum(a, b, c, d, 40); 35 System.out.println("result:" + result); // 130 36 37 result = sum(a, b, c, d, 40, 50); 38 System.out.println("result:" + result); // 180 39 } 40 41 public static int sum(int... a) { 42 // System.out.println(a); // [I@1f297e7 43 // return 0; 44 45 int s = 0; 46 47 for (int x : a) { 48 s += x; 49 } 50 51 return s; 52 } 53 54 // public static int sum(int a, int b, int c, int d) { 55 // return a + b + c + d; 56 // } 57 // 58 // public static int sum(int a, int b, int c) { 59 // return a + b + c; 60 // } 61 // 62 // public static int sum(int a, int b) { 63 // return a + b; 64 // } 65 } ArgsDemo.java -----------------------------------------------------------------------------5:可变参数(掌握) (1)可变参数的概述 如果我们在写方法的时候,参数个数不明确,就应该定义可变参数。 (2)可变参数的格式 修饰符 返回值类型 方法名(数据类型… 变量名){ } public static int sum(int... a) { } (3)注意事项 虽然可以把数组转成集合,但是集合的长度不能改变。 (4)Arrays工具类中的一个方法 public static <T> List<T> asList(T... a) 把数组转成集合 注意:虽然可以把数组转成集合,但是集合的长度不能改变。 因为这个集合的本质是数组。 1 package cn.itcast_03; 2 3 import java.util.Arrays; 4 import java.util.List; 5 6 /* 7 * Arrays工具类中的一个方法 8 * public static <T> List<T> asList(T... a) 把数组转成集合 9 * 10 * 注意事项: 11 * 虽然可以把数组转成集合,但是集合的长度不能改变。 12 */ 13 public class ArraysDemo { 14 public static void main(String[] args) { 15 // 定义一个数组 16 // String[] strArray = { "hello", "world", "java" }; 17 // List<String> list = Arrays.asList(strArray); 18 19 List<String> list = Arrays.asList("hello", "world", "java"); 20 // UnsupportedOperationException 不支持的操作异常 21 // list.add("javaee"); 22 // UnsupportedOperationException 不支持的操作异常 23 // list.remove(1); 24 list.set(1, "javaee"); // 可以修改 25 26 for (String s : list) { 27 System.out.println(s); 28 } 29 } 30 } ArraysDemo.java -----------------------------------------------------------------------------6:练习(掌握) A:集合的嵌套遍历 1 package cn.itcast_01; 2 3 public class Student { 4 private String name; 5 private int age; 6 7 public Student() { 8 super(); 9 } 10 11 public Student(String name, int age) { 12 super(); 13 this.name = name; 14 this.age = age; 15 } 16 17 public String getName() { 18 return name; 19 } 20 21 public void setName(String name) { 22 this.name = name; 23 } 24 25 public int getAge() { 26 return age; 27 } 28 29 public void setAge(int age) { 30 this.age = age; 31 } 32 33 } Student.java 1 package cn.itcast_01; 2 3 import java.util.ArrayList; 4 5 /* 6 * 集合的嵌套遍历 7 * 需求: 8 * 我们班有学生,每一个学生是不是一个对象。所以我们可以使用一个集合表示我们班级的学生。ArrayList<Student> 9 * 但是呢,我们旁边是不是还有班级,每个班级是不是也是一个ArrayList<Student>。 10 * 而我现在有多个ArrayList<Student>。也要用集合存储,怎么办呢? 11 * 就是这个样子的:ArrayList<ArrayList<Student>> 12 */ 13 public class ArrayListDemo { 14 public static void main(String[] args) { 15 // 创建大集合 16 ArrayList<ArrayList<Student>> bigArrayList = new ArrayList<ArrayList<Student>>(); 17 18 // 创建第一个班级的学生集合 19 ArrayList<Student> firstArrayList = new ArrayList<Student>(); 20 // 创建学生 21 Student s1 = new Student("唐僧", 30); 22 Student s2 = new Student("孙悟空", 29); 23 Student s3 = new Student("猪八戒", 28); 24 Student s4 = new Student("沙僧", 27); 25 Student s5 = new Student("白龙马", 26); 26 // 学生进班 27 firstArrayList.add(s1); 28 firstArrayList.add(s2); 29 firstArrayList.add(s3); 30 firstArrayList.add(s4); 31 firstArrayList.add(s5); 32 // 把第一个班级存储到学生系统中 33 bigArrayList.add(firstArrayList); 34 35 // 创建第二个班级的学生集合 36 ArrayList<Student> secondArrayList = new ArrayList<Student>(); 37 // 创建学生 38 Student s11 = new Student("诸葛亮", 30); 39 Student s22 = new Student("司马懿", 28); 40 Student s33 = new Student("周瑜", 26); 41 // 学生进班 42 secondArrayList.add(s11); 43 secondArrayList.add(s22); 44 secondArrayList.add(s33); 45 // 把第二个班级存储到学生系统中 46 bigArrayList.add(secondArrayList); 47 48 // 创建第三个班级的学生集合 49 ArrayList<Student> thirdArrayList = new ArrayList<Student>(); 50 // 创建学生 51 Student s111 = new Student("宋江", 40); 52 Student s222 = new Student("吴用", 35); 53 Student s333 = new Student("高俅", 30); 54 Student s444 = new Student("李师师", 22); 55 // 学生进班 56 thirdArrayList.add(s111); 57 thirdArrayList.add(s222); 58 thirdArrayList.add(s333); 59 thirdArrayList.add(s444); 60 // 把第三个班级存储到学生系统中 61 bigArrayList.add(thirdArrayList); 62 63 // 遍历集合 64 for (ArrayList<Student> array : bigArrayList) { 65 for (Student s : array) { 66 System.out.println(s.getName() + "---" + s.getAge()); 67 } 68 } 69 } 70 } ArrayListDemo.java B:产生10个1-20之间的随机数,要求随机数不能重复 1 package cn.itcast_02; 2 3 import java.util.ArrayList; 4 import java.util.Random; 5 6 /* 7 * 获取10个1-20之间的随机数,要求不能重复 8 * 9 * 用数组实现,但是数组的长度是固定的。 10 * 长度不好确定,所以我们使用集合实现。 11 * 12 * 分析: 13 * A:创建产生随机数的对象。 14 * B:创建一个存储随机数的集合。 15 * C:定义一个统计变量。从0开始。 16 * D:判断统计遍历是否小于10 17 * 是:产生一个随机数,判断该随机数在集合中是否存在。 18 * 如果不存在:就添加,统计变量++。 19 * 如果存在:就不搭理它。 20 * 否:不搭理它 21 * E:遍历集合 22 */ 23 public class RandomDemo { 24 public static void main(String[] args) { 25 // 创建产生随机数的对象。 26 Random r = new Random(); 27 28 // 创建一个存储随机数的集合。 29 ArrayList<Integer> array = new ArrayList<Integer>(); 30 31 // 定义一个统计变量。从0开始。 32 int count = 0; 33 34 // 判断统计遍历是否小于10 35 while (count < 10) { 36 // 产生一个随机数 37 int number = r.nextInt(20) + 1; 38 39 // 判断该随机数在集合中是否存在。 40 if (!array.contains(number)) { 41 // 如果不存在:就添加,统计变量++。 42 array.add(number); 43 count++; 44 } 45 } 46 47 // 遍历集合 48 for (Integer i : array) { 49 System.out.println(i); 50 } 51 } 52 } RandomDemo.java C:键盘录入多个数据,以0结束,并在控制台输出最大值 1 package cn.itcast_03; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.Scanner; 6 7 /* 8 * 键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值。 9 * 10 * 分析: 11 * A:创建键盘录入数据对象 12 * B:键盘录入多个数据,我们不知道多少个,所以用集合存储 13 * C:以0结束,这个简单,只要键盘录入的数据是0,我就不继续录入数据了 14 * D:把集合转成数组 15 * E:对数组排序 16 * F:获取该数组中的最大索引的值 17 */ 18 public class ArrayListDemo { 19 public static void main(String[] args) { 20 // 创建键盘录入数据对象 21 Scanner sc = new Scanner(System.in); 22 23 // 键盘录入多个数据,我们不知道多少个,所以用集合存储 24 ArrayList<Integer> array = new ArrayList<Integer>(); 25 26 // 以0结束,这个简单,只要键盘录入的数据是0,我就不继续录入数据了 27 while (true) { 28 System.out.println("请输入数据:"); 29 int number = sc.nextInt(); 30 if (number != 0) { 31 array.add(number); 32 } else { 33 break; 34 } 35 } 36 37 // 把集合转成数组 38 // public <T> T[] toArray(T[] a) 39 Integer[] i = new Integer[array.size()]; 40 // Integer[] ii = array.toArray(i); 41 array.toArray(i); 42 // System.out.println(i); // [Ljava.lang.Integer;@6cd8737 43 // System.out.println(ii); // [Ljava.lang.Integer;@6cd8737 44 45 // 对数组排序 46 // public static void sort(Object[] a) 47 Arrays.sort(i); 48 49 // 获取该数组中的最大索引的值 50 System.out.println("数组是:" + arrayToString(i) + "最大值是:" + i[i.length - 1]); 51 } 52 53 // 把数组转换成字符串 54 public static String arrayToString(Integer[] i) { 55 StringBuilder sb = new StringBuilder(); 56 57 sb.append("["); 58 for (int x = 0; x < i.length; x++) { 59 if (x == i.length - 1) { 60 sb.append(i[x]); 61 } else { 62 sb.append(i[x]).append(", "); 63 } 64 } 65 sb.append("]"); 66 67 return sb.toString(); 68 } 69 } ArrayListDemo.java ----------------------------------------------------------------------------- 7:要掌握的代码 集合存储元素,加入泛型,并可以使用增强for遍历。=============================================================================我的GitHub地址: https://github.com/heizemingjun 我的博客园地址: http://www.cnblogs.com/chenmingjun 我的蚂蚁笔记博客地址: http://blog.leanote.com/chenmingjun Copyright ©2018 黑泽明军 【转载文章务必保留出处和署名,谢谢!】

优秀的个人博客,低调大师

【读书笔记《Android游戏编程之从零开始》】9.游戏开发基础(如何快速的进入 Android 游戏开发)

1.不可盲目看API文档 很多人在接触学习一门新的平台语言时,总喜欢先去探究一番API文档。先不说成效如何,至少编者认为这种方式不适合大部分人来效仿,主要原因在于 API 领域广泛,牵涉到的知识点太多,而对于刚刚接触平台开发语言的大部分人来说,遗忘速度远远大于记忆!这种做法是大量消耗精力、小量吸取知识的方法,只会事倍功半。2.前人栽树,后人乘凉 对于初学者来说,任何想要学习与掌握的知识点,之前都会有高人总结过;所以建议大家每学习一个知识点,都尽可能的先动手去网上搜索和学习别人总结出来的相关知识点的文章,毕竟前任总结的知识会让你减少学习的弯路。最后再根据每个知识点去详细翻阅相关的 API 文档,有针对性、有目的性的去看 API 文档才会是事半功倍。3.好记性不如烂笔头 这句谚语,几乎无人不知无人不晓,但是总被许多初学者抛在脑后。在学习的时候,总是看代码多,而动手练习代码少!身为一个程序员都应该很清楚,代码如果不多动手敲它,它永远不会自己跑进脑中,所以多动手才是成功的关键。4.养成自学的习惯 学习新的知识如果总是抱着依赖和期望别人手把手教授,那就不太现实了。因为没有任何一个人能时时刻刻的陪在身边给予帮助,但是使用 Baidu 和 Google 可以做到!它们拥有着最全的资源库,使用它们可以查找到最强的技术,不过,它们永远都只在那里等待你去使用它们,如果你不动手去搜索,那么对于你来说它们毫无用处。5.利用小项目实战进步快 在学习游戏开发时,一定要多做小项目,比如今天学会了一个新的知识点,那么首先就要尽可能发散思维,多思考这个知识点会应用到什么类型的游戏中,并在游戏中起到什么样的作用等等。然后拿出时间一定要去写一个小项目联系新知识点。 写小项目有两点好处:一是巩固新知识点;二是通过小项目发现知识点实际应用到游戏中会出现的问题,有些问题不亲自动手编写是根本无法发现的。6.进步来源于问题 好程序不是写出来的,是改出来的!这句话没有人能反驳,因为谁写代码都不可能是一遍成功,不用修改不用完善的。 学习中遇到问题时,不应该烦躁而是应该庆幸,因为解决掉问题就意味着进步。千万不要出到问题不假思索就去请教他人,这样解决掉的问题没有任何意义。 当然不推荐大家遇到问题一定就铁下心的自己去几天几夜的钻研,应该自我把握问题的难易度,如果问题确实超出自己能力的,那么请教他人反而对自己更有帮助,有效率,前提是自己考虑过如何解决此问题。 其实,游戏开发的学习过程应该是一个拼图的过程.首先要分模块来学习,积累了一定的模块知识后,再通过这些模块就可以拼出各种类型\各种风格的游戏。 在游戏开发中,一般很少使用系统提供的组件进行开发,其主要原因在于游戏的多样性.比如一款"连连看"游戏,它就可以有N种玩法、N种场景、N种风格、N种元素.所以,如果还期望从系统中找到对应组件的话,结果会令人失望,不是系统不想提供,而是它永远无法知道将要制作的游戏类型、风格等等。总结一句话: 开发一款游戏,请用自己的双手为这款游戏创建专属它的组件!换言之,就是要自己去实现游戏中的组件,不要再一味的幻想系统能为你带来什么。系统只提供“一支笔”、“一张画布”,仅此而已。至于能创造出多么精彩的游戏世界,那完全取决于游戏开发者。 本文转自叶超Luka博客园博客,原文链接:http://www.cnblogs.com/yc-755909659/p/4134758.html,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册