【原】Java学习笔记027 - 泛型
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 public class Sample01 { 7 public static void main(String[] args) { 8 ArrayList arrayList = new ArrayList(); 9 10 arrayList.add("中国"); 11 arrayList.add("美国"); 12 // 下句会导致执行异常:java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 13 arrayList.add(250); 14 15 Iterator iterator = arrayList.iterator(); 16 17 while (iterator.hasNext()) { 18 // 因为在向ArrayList对象中添加元素时,add方法的参数类型为Object类型,换句话说,在添加元素时没有做类型检查 19 // 在遍历时,强行要求取出的是某一种数据类型 20 String item = (String) iterator.next(); 21 // 上句改为下句,执行时不会有异常产生 22 // Object item = iterator.next(); 23 24 System.out.println(item); 25 } 26 27 // 回忆一下,前面使用另一种容器-----数组时,没有出现过取出数据时数据类型不匹配的错误,为何? 28 // 这是因为数组在创建时,就已经规定好了其中的元素是什么数据类型 29 // 数组的这种特点属于"丑话讲在前",即在编译阶段就提示语法错误的写法具有较好的前瞻性 30 // int[] arrInt = { 1, 2, 3, "abc" }; 31 // String[] arrString = { "abc", "admin", 123, "test" }; 32 33 // 我们希望在集合的使用中,也有数组的这种优点,即在编译阶段就提示出语法错误的功能 34 // 换句话说,就是在编译阶段就能强制确定集合中的元素的数据类型 35 36 // Java中引入了 泛型(Generic),从JDK 1.5之后引入的,大家维护早期项目时无法使用泛型的 37 } 38 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 public class Sample02 { 7 public static void main(String[] args) { 8 /* 9 * 泛型(Generic) 10 * 11 * 定义:把类型确定的工作推迟到创建对象或方法调用时才做的方式 12 * 13 * 格式:<数据类型> 14 * 15 * 注意:泛型中的数据类型只能是引用数据类型,参数化类型(或者称为不明确具体的类型),也就是把数据类型作为参数一样进行传递 16 * 17 * 优点: 18 * 1、把执行时才能发现的问题提前到编译时发现并处理 19 * 2、避免强制类型转换 20 * 3、让程序中不再到处都出现警告 21 * 22 * 理解: 23 * 泛型,开始会觉得泛型的"泛"是否指的是有宽泛、广泛的意思,使用后发现使用了泛型,其实对数据类型带来强制性,也就是"泛型不泛" 24 * 25 */ 26 // 在JDK 1.7之前,创建泛型对象时,如下写法: 27 // ArrayList<String> arrayList = new ArrayList<String>(); 28 // 在JDK 1.7之后,创建泛型对象时,简化为如下写法: 29 ArrayList<String> arrayList = new ArrayList<>(); 30 31 arrayList.add("中国"); 32 arrayList.add("美国"); 33 // 创建了泛型的ArrayList对象后,因为指明了该集合对象中的元素类型为String类型,再向其中放入其他数据类型的元素时,就提示出错了 34 // 【在编译阶段暴露问题 远远好于 在执行阶段暴露问题】 35 // 语法错误:The method add(int, String) in the type ArrayList<String> is not applicable for the arguments (int) 36 // arrayList.add(250); 37 38 Iterator<String> iterator = arrayList.iterator(); 39 40 while (iterator.hasNext()) { 41 String item = iterator.next(); 42 System.out.println(item); 43 } 44 } 45 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 public class Sample03 { 7 public static void main(String[] args) { 8 /* 9 * 泛型可以用在哪些地方? 10 * 1、泛型用在类上,称为泛型类 11 * 2、泛型用在接口上,称为泛型接口 12 * 3、泛型用在方法上,称为泛型方法 13 */ 14 15 ArrayList<String> arrayList = new ArrayList<>(); 16 17 arrayList.add("China"); 18 arrayList.add("USA"); 19 20 Iterator<String> iterator = arrayList.iterator(); 21 22 while (iterator.hasNext()) { 23 String item = (String) iterator.next(); 24 System.out.println(item); 25 } 26 } 27 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 public class Sample04 { 7 public static void main(String[] args) { 8 // 需求:使用泛型ArrayList和Iterator存放并遍历三个学生对象 9 ArrayList<Student> arrayList = new ArrayList<>(); 10 11 arrayList.add(new Student("张三", 20)); 12 arrayList.add(new Student("李四", 22)); 13 arrayList.add(new Student("王五", 18)); 14 15 Iterator<Student> iterator = arrayList.iterator(); 16 17 while (iterator.hasNext()) { 18 Student item = (Student) iterator.next(); 19 System.out.println(item); 20 } 21 } 22 }
1 package cn.temptation.test; 2 3 public class Sample05 { 4 public static void main(String[] args) { 5 /* 6 * 泛型没有出现时,使用Object类型作为引用数据类型转换的桥梁 7 */ 8 ObjectTool objectTool = new ObjectTool(); 9 10 objectTool.setObj(new Student("张三", 20)); 11 12 Object obj = objectTool.getObj(); 13 System.out.println(obj); 14 15 // 对Object工具类返回的对象使用具体类型,就必须使用强制类型转换(向下转型) 16 Student student = (Student) objectTool.getObj(); 17 System.out.println(student); 18 19 // 因为向下转型使用强制类型转换,会有风险 20 // 为了能无异常的进行向下转型,必须要清楚的知道向上转型时元素的数据类型 21 // 执行产生异常:java.lang.ClassCastException: cn.temptation.Student cannot be cast to java.lang.String 22 String str = (String) objectTool.getObj(); 23 System.out.println(str); 24 } 25 }
1 package cn.temptation.test; 2 3 /** 4 * 对象工具类 5 */ 6 public class ObjectTool { 7 // 成员变量 8 private Object obj; 9 10 // 成员方法 11 public Object getObj() { 12 return obj; 13 } 14 15 public void setObj(Object obj) { 16 this.obj = obj; 17 } 18 }
1 package cn.temptation.test; 2 3 public class Sample06 { 4 public static void main(String[] args) { 5 ObjectToolEx<Student> objectToolEx = new ObjectToolEx<>(); 6 7 objectToolEx.setObj(new Student("张三", 20)); 8 // 语法错误:The method setObj(Student) in the type ObjectToolEx<Student> is not applicable for the arguments (int) 9 // objectToolEx.setObj(123); 10 // 语法错误:The method setObj(Student) in the type ObjectToolEx<Student> is not applicable for the arguments (String) 11 // objectToolEx.setObj("abc"); 12 // 语法错误:The method setObj(Student) in the type ObjectToolEx<Student> is not applicable for the arguments (Integer) 13 // objectToolEx.setObj(new Integer(456)); 14 15 // 理解:泛型 -----> 范型(规范类型),"泛型有范" 16 } 17 }
1 package cn.temptation.test; 2 3 /** 4 * 对象工具类(泛型版):使用泛型对ObjectTool工具类进行升级 5 * 6 * 思路: 7 * 原来使用Object类作为方法形参的类型以及成员变量的类型,都是出于通用性的考虑(即越抽象越好) 8 * 现在在类的声明时,不急于确定传入进来的对象到底是什么类型,而是使用占位符把位置先占住,在使用时,根据传入进来的数据类型进行相应的设置 9 * 优点在于使用时明确到底用什么类型,避免了强制类型转换 10 * 使用泛型的占位符,先不需要知道数据类型是什么,推迟到类的实例化(具体使用时)再去替换为对应的数据类型 11 */ 12 public class ObjectToolEx<T> { 13 // 成员变量 14 private T obj; 15 private T resultT; 16 // 语法错误:E cannot be resolved to a type 17 // private E resultE; 18 19 // 成员方法 20 public T getObj() { 21 return obj; 22 } 23 24 public void setObj(T obj) { 25 this.obj = obj; 26 } 27 28 // 泛型方法1、参数类型与类的类型一致 29 public void show(T param) { 30 System.out.println(param); 31 } 32 33 public T showEx(T param) { 34 return resultT; 35 } 36 37 // 泛型方法2、参数类型与类的类型不一致 38 public <E> void method(E param) { 39 System.out.println(param); 40 } 41 42 // 泛型方法的返回值类型和其所在泛型类不一致时,只能返回null值,返回其他类型语法错误 43 public <E> E methodEx(E param) { 44 // 语法错误:resultE cannot be resolved to a variable 45 // return resultE; 46 47 // 下面写法语法OK,但是返回的是null值 48 return null; 49 } 50 }
1 package cn.temptation.test; 2 3 public class Sample07 { 4 public static void main(String[] args) { 5 // 泛型类的使用,可以传递的数据类型只能是引用数据类型 6 // ObjectToolEx<String> objectToolEx = new ObjectToolEx<>(); 7 // objectToolEx.setObj("java"); 8 // System.out.println(objectToolEx.getObj()); 9 10 // 语法错误:Syntax error, insert "Dimensions" to complete ReferenceType 11 // ObjectToolEx<int> objectToolEx = new ObjectToolEx<>(); 12 } 13 }
1 package cn.temptation.test; 2 3 public class Sample08 { 4 public static void main(String[] args) { 5 // 泛型方法的定义,参数可以和其所在的泛型类的类型相同,也可以不相同 6 // 参数不相同的使用时,根据传入的数据类型进行相应的使用 7 8 ObjectToolEx<String> objectToolEx = new ObjectToolEx<>(); 9 10 objectToolEx.show("admin"); // admin 11 System.out.println(objectToolEx.showEx("test")); // null 12 13 objectToolEx.method(123); // 123 14 System.out.println(objectToolEx.methodEx(true)); // null 15 } 16 }
1 package cn.temptation.test; 2 3 public class Sample09 { 4 public static void main(String[] args) { 5 // 1、创建泛型接口时,已经明确泛型接口使用的数据类型是什么类型 6 Foo<String> foo1 = new FooImpl(); 7 foo1.show("java"); 8 9 // 2、创建接口的实现类对象时,才传入泛型接口使用的数据类型是什么类型 10 Foo<Integer> foo2 = new FooImplEx<>(); 11 foo2.show(123); 12 } 13 }
1 package cn.temptation.test; 2 3 /** 4 * 泛型接口 5 * @param <T> 6 */ 7 public interface Foo<T> { 8 public abstract void show(T param); 9 }
1 package cn.temptation.test; 2 3 /** 4 * 制作泛型接口的实现类时,已经知道泛型接口使用的是什么数据类型 5 */ 6 public class FooImpl implements Foo<String> { 7 // 既然已经知道泛型接口使用的是什么数据类型,那么重写的成员方法也就明确使用什么数据类型 8 @Override 9 public void show(String param) { 10 System.out.println(param); 11 } 12 }
1 package cn.temptation.test; 2 3 /** 4 * 制作泛型接口的实现类时,还不知道泛型接口使用的是什么数据类型 5 * 实现类需要和泛型接口使用相同数据类型的占位符 6 * 7 * @param <T> 8 */ 9 public class FooImplEx<T> implements Foo<T> { 10 // 既然还不知道泛型接口使用的是什么数据类型,那么重写的成员方法也就不能明确使用什么数据类型,那么还是使用占位符先占住位置 11 @Override 12 public void show(T param) { 13 System.out.println(param); 14 } 15 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 6 public class Sample10 { 7 public static void main(String[] args) { 8 /* 9 * 泛型的通配符 10 * ? :任意类型 11 * ? extends T :向下限定,指的是 ? 对应的类型必须是 T 对应的类型的子类或自身 12 * ? super T :向上限定,指的是 ? 对应的类型必须是 T 对应的类型的父类或自身 13 */ 14 15 Collection<Object> collection1 = new ArrayList<Object>(); 16 Collection<Animal> collection2 = new ArrayList<Animal>(); 17 Collection<Dog> collection3 = new ArrayList<Dog>(); 18 19 // 使用 ? 泛型表示任意类型 20 Collection<?> collection4 = new ArrayList<Object>(); 21 Collection<?> collection5 = new ArrayList<Animal>(); 22 Collection<?> collection6 = new ArrayList<Dog>(); 23 24 // 使用 ? extends T :向下限定,指的是 ? 对应的类型必须是 T 对应的类型的子类或自身 25 // 语法错误:Type mismatch: cannot convert from ArrayList<Object> to Collection<? extends Animal> 26 // Collection<? extends Animal> collection7 = new ArrayList<Object>(); 27 Collection<? extends Animal> collection8 = new ArrayList<Animal>(); 28 Collection<? extends Animal> collection9 = new ArrayList<Dog>(); 29 30 // 使用? super T :向上限定,指的是 ? 对应的类型必须是 T 对应的类型的父类或自身 31 Collection<? super Animal> collection10 = new ArrayList<Object>(); 32 Collection<? super Animal> collection11 = new ArrayList<Animal>(); 33 // 语法错误:Type mismatch: cannot convert from ArrayList<Dog> to Collection<? super Animal> 34 // Collection<? super Animal> collection12 = new ArrayList<Dog>(); 35 } 36 } 37 38 class Animal extends Object { 39 40 } 41 42 class Dog extends Animal { 43 44 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Iterator; 6 7 public class Sample11 { 8 public static void main(String[] args) { 9 /* 10 * 使用集合存储元素,有哪些遍历的方式? 11 * 1、使用一般for循环(结合size方法和get方法) 12 * 2、使用迭代器 13 * 3、使用增强型for循环 14 * 15 * Iterable接口:实现这个接口允许对象成为 "foreach" 语句的目标。 16 * 17 * 注意:增强型for循环可以认为是简化使用迭代器 18 */ 19 20 Collection<String> collection = new ArrayList<>(); 21 22 collection.add("中国"); 23 collection.add("美国"); 24 25 System.out.println("collection:" + collection); // collection:[中国, 美国] 26 27 // 1、使用一般for循环(结合size方法和get方法) 28 for (int i = 0; i < collection.size(); i++) { 29 // 下面两种写法效果一致 30 // String item = ((List<String>)collection).get(i); 31 String item = ((ArrayList<String>)collection).get(i); 32 33 System.out.println(item); 34 } 35 36 System.out.println("---------------------------------------------------------------"); 37 38 // 2、使用迭代器 39 Iterator<String> iterator = collection.iterator(); 40 41 while (iterator.hasNext()) { 42 String item = (String) iterator.next(); 43 System.out.println(item); 44 } 45 46 System.out.println("---------------------------------------------------------------"); 47 48 // 3、使用增强型for循环 49 for (String item : collection) { 50 System.out.println(item); 51 } 52 } 53 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Iterator; 6 7 public class Sample12 { 8 public static void main(String[] args) { 9 /* 10 * 使用集合存储元素,有哪些遍历的方式? 11 * 1、使用一般for循环(结合size方法和get方法) 12 * 2、使用迭代器 13 * 3、使用增强型for循环 14 * 15 * Iterable接口:实现这个接口允许对象成为 "foreach" 语句的目标。 16 * 17 * 注意:增强型for循环可以认为是简化使用迭代器 18 */ 19 Collection<Student> collection = new ArrayList<>(); 20 21 collection.add(new Student("张三", 20)); 22 collection.add(new Student("李四", 18)); 23 24 System.out.println("collection:" + collection); // collection:[中国, 美国] 25 26 // 1、使用一般for循环(结合size方法和get方法) 27 for (int i = 0; i < collection.size(); i++) { 28 // 下面两种写法效果一致 29 // Student item = ((List<Student>)collection).get(i); 30 Student item = ((ArrayList<Student>)collection).get(i); 31 32 System.out.println(item); 33 } 34 35 System.out.println("---------------------------------------------------------------"); 36 37 // 2、使用迭代器 38 Iterator<Student> iterator = collection.iterator(); 39 40 while (iterator.hasNext()) { 41 Student item = (Student) iterator.next(); 42 System.out.println(item); 43 } 44 45 System.out.println("---------------------------------------------------------------"); 46 47 // 3、使用增强型for循环 48 for (Student item : collection) { 49 System.out.println(item); 50 } 51 } 52 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Iterator; 6 7 public class Sample13 { 8 public static void main(String[] args) { 9 Collection<String> collection = new ArrayList<>(); 10 11 collection = null; 12 13 System.out.println("collection:" + collection); // collection:[] 14 15 // 执行异常:java.lang.NullPointerException 16 // 使用一般for循环遍历 17 // for (int i = 0; i < collection.size(); i++) { 18 //// String item = ((List<String>)collection).get(i); 19 // String item = ((ArrayList<String>)collection).get(i); 20 // 21 // System.out.println(item); 22 // } 23 24 // 执行异常:java.lang.NullPointerException 25 // 使用迭代器遍历 26 // Iterator<String> iterator = collection.iterator(); 27 // 28 // while (iterator.hasNext()) { 29 // String item = (String) iterator.next(); 30 // System.out.println(item); 31 // } 32 33 // 执行异常:java.lang.NullPointerException 34 // 使用增强型for循环遍历 35 // for (String item : collection) { 36 // System.out.println(item); 37 // } 38 39 // 上述三种遍历形式对于集合对象为null值均缺乏必要的检查操作 40 // 所以遍历集合时,应该手工添加检查 41 if (collection != null) { 42 for (String item : collection) { 43 System.out.println(item); 44 } 45 } 46 } 47 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.Collection; 6 import java.util.List; 7 8 public class Sample14 { 9 public static void main(String[] args) { 10 /* 11 * 类 Arrays:此类包含用来操作数组(比如排序和搜索)的各种方法。 12 * 13 * Arrays类的常用成员方法: 14 * static <T> List<T> asList(T... a) :返回一个受指定数组支持的固定大小的列表。 15 * 16 * 【数组转换为集合】的常用方法 17 */ 18 String[] arrStr = { "中国", "美国", "日本" }; 19 20 List<String> list1 = Arrays.asList(arrStr); 21 22 for (String item : list1) { 23 System.out.println(item); 24 } 25 26 System.out.println("-------------------------------------------------"); 27 28 // 语法错误:Syntax error on token ".", @ expected after this token 29 // List<String> list2 = Arrays.asList({ "中国", "美国", "日本" }); 30 // 正确写法:可变长参数的理解,参数有多少无所谓,这些参数识别为是数组的元素 31 List<String> list2 = Arrays.asList("中国", "美国", "日本"); 32 33 for (String item : list2) { 34 System.out.println(item); 35 } 36 37 System.out.println("-------------------------------------------------"); 38 39 // 【集合转换为数组】的常用方法 40 // Collection接口的常用成员方法: 41 // 1、Object[] toArray() :返回包含此 collection 中所有元素的数组。 42 // 2、<T> T[] toArray(T[] a) :返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。 43 44 Collection<String> collection = new ArrayList<>(); 45 46 collection.add("中国"); 47 collection.add("美国"); 48 collection.add("日本"); 49 50 Object[] arr1 = collection.toArray(); 51 for (Object item : arr1) { 52 System.out.println(item); 53 } 54 55 System.out.println("-------------------------------------------------"); 56 57 // String[] arr2 = (String[]) collection.toArray(); 58 // // 执行异常:java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String; 59 // for (String item : arr2) { 60 // System.out.println(item); 61 // } 62 63 String[] arrTemp = new String[collection.size()]; 64 String[] arr3 = collection.toArray(arrTemp); 65 66 for (String item : arr3) { 67 System.out.println(item); 68 } 69 70 for (String item : arrTemp) { 71 System.out.println(item); 72 } 73 } 74 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 6 public class Sample15 { 7 public static void main(String[] args) { 8 // 需求:使用集合和泛型,存储5个同学:张三 20岁,李四 18岁,王五 22岁,赵六 19岁,钱七 20岁 9 10 Collection<Student> collection = new ArrayList<>(); 11 12 collection.add(new Student("张三", 20)); 13 collection.add(new Student("李四", 18)); 14 collection.add(new Student("王五", 22)); 15 collection.add(new Student("赵六", 19)); 16 collection.add(new Student("钱七", 20)); 17 18 System.out.println("collection:" + collection); 19 20 for (Student item : collection) { 21 System.out.println(item); 22 } 23 } 24 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Iterator; 6 import java.util.List; 7 8 public class Sample16 { 9 public static void main(String[] args) { 10 // 需求:把上个例子中的五个同学分为两组进行存储,前三个同学一组,后两个同学一组 11 12 // 思路: 13 // 回顾一下,数组是容器,数组中可以放入数组(容器里可以嵌套容器),所以,集合也是容器,集合中也可以嵌套集合 14 15 // 创建组的容器 16 Collection<Student> team1 = new ArrayList<>(); 17 18 team1.add(new Student("张三", 20)); 19 team1.add(new Student("李四", 18)); 20 team1.add(new Student("王五", 22)); 21 22 // 创建组的容器 23 Collection<Student> team2 = new ArrayList<>(); 24 25 team2.add(new Student("赵六", 19)); 26 team2.add(new Student("钱七", 20)); 27 28 // 创建班级的容器来存放组的容器 29 Collection<Collection<Student>> clazz = new ArrayList<>(); 30 31 clazz.add(team1); 32 clazz.add(team2); 33 34 System.out.println("clazz:" + clazz); 35 36 // 遍历嵌套集合的集合 37 38 // 增强型for循环的遍历 39 for (Collection<Student> team : clazz) { 40 for (Student item : team) { 41 System.out.println(item); 42 } 43 } 44 45 System.out.println("---------------------------------------------"); 46 47 // 迭代器的遍历 48 49 // 外层的迭代器在班级集合上 50 Iterator<Collection<Student>> iterator = clazz.iterator(); 51 52 while (iterator.hasNext()) { 53 Collection<Student> team = (Collection<Student>) iterator.next(); 54 55 // 内层的迭代器在组集合上 56 Iterator<Student> iteratorEx = team.iterator(); 57 58 while (iteratorEx.hasNext()) { 59 Student item = (Student) iteratorEx.next(); 60 System.out.println(item); 61 } 62 } 63 64 System.out.println("---------------------------------------------"); 65 66 // 一般for循环的遍历 67 for (int i = 0; i < clazz.size(); i++) { 68 List<Student> team = (List<Student>)(((List<Collection<Student>>)clazz).get(i)); 69 70 for (int j = 0; j < team.size(); j++) { 71 Student item = team.get(j); 72 System.out.println(item); 73 } 74 } 75 } 76 }
1 package cn.temptation.test; 2 3 public class Student { 4 // 成员变量 5 private String name; 6 private int age; 7 8 // 构造函数 9 public Student() { 10 super(); 11 } 12 13 public Student(String name, int age) { 14 super(); 15 this.name = name; 16 this.age = age; 17 } 18 19 // 成员方法 20 public String getName() { 21 return name; 22 } 23 24 public void setName(String name) { 25 this.name = name; 26 } 27 28 public int getAge() { 29 return age; 30 } 31 32 public void setAge(int age) { 33 this.age = age; 34 } 35 36 @Override 37 public String toString() { 38 return "学生 [姓名为:" + name + ", 年龄为:" + age + "]"; 39 } 40 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Iterator; 6 import java.util.Scanner; 7 8 public class Sample18 { 9 public static void main(String[] args) { 10 // 需求:使用集合和泛型,通过键盘录入一些整数,以录入整数0作为录入的结束。 11 // 判断录入的整数的大小,显示出录入的整数,形如:{整数1,整数2,...整数n},并显示最大整数是多少 12 13 // 思路1: 14 // 1、因为录入的整数个数未知,所以选择容器时,不选择数组,而是选择集合来存储数据 15 // 2、通过键盘录入整数,考虑使用死循环,判断录入的数字为0时跳出死循环 16 // 3、比较大小(通过遍历集合中元素进行比较) 17 // 4、打印结果,大量字符串的拼接考虑使用字符串缓冲区 18 19 // 写法1 20 21 // 创建容器对象 22 Collection<Integer> collection = new ArrayList<>(); 23 // 声明最大整数变量 24 int max = 0; 25 26 // 接收键盘录入,把录入的数据放入容器中 27 Scanner input = new Scanner(System.in); 28 while (true) { 29 System.out.println("输入若干个整数:"); 30 Integer i = input.nextInt(); 31 if (i == 0) { // 判断录入的数字为0时跳出死循环 32 break; 33 } else { 34 collection.add(i); 35 } 36 } 37 input.close(); 38 39 if (collection.size() > 0) { // 判断集合中是否有元素 40 // 创建字符串缓冲区对象 41 StringBuffer sb = new StringBuffer("录入的整数为:{"); 42 43 // 遍历容器进行比较 44 Iterator<Integer> iterator = collection.iterator(); 45 46 while (iterator.hasNext()) { 47 Integer item = (Integer) iterator.next(); 48 49 // 比较大小 50 if (item > max) { 51 max = item; 52 } 53 54 // 遍历到的元素添加到字符串缓冲区对象中 55 sb.append(item + ","); 56 } 57 58 // 上述遍历操作会在最后一个元素获取放入到字符串缓冲区对象中时多添加一个逗号 59 String str = sb.substring(0, sb.length() - 1) + "}"; 60 61 System.out.println(str + ",最大整数为:" + max); 62 } 63 } 64 }
1 package cn.temptation.test; 2 3 import java.util.ArrayList; 4 import java.util.Arrays; 5 import java.util.Collection; 6 import java.util.Scanner; 7 8 public class Sample19 { 9 public static void main(String[] args) { 10 // 需求:使用集合和泛型,通过键盘录入一些整数,以录入整数0作为录入的结束。 11 // 判断录入的整数的大小,显示出录入的整数,形如:{整数1,整数2,...整数n},并显示最大整数是多少 12 13 // 思路2: 14 // 1、因为录入的整数个数未知,所以选择容器时,不选择数组,而是选择集合来存储数据 15 // 2、通过键盘录入整数,考虑使用死循环,判断录入的数字为0时跳出死循环 16 // 3、比较大小(通过Arrays类的sort方法进行排序) 17 // 4、打印结果,大量字符串的拼接考虑使用字符串缓冲区 18 19 // 写法1 20 21 // 创建容器对象 22 Collection<Integer> collection = new ArrayList<>(); 23 24 // 接收键盘录入,把录入的数据放入容器中 25 Scanner input = new Scanner(System.in); 26 while (true) { 27 System.out.println("输入若干个整数:"); 28 Integer i = input.nextInt(); 29 if (i == 0) { // 判断录入的数字为0时跳出死循环 30 break; 31 } else { 32 collection.add(i); 33 } 34 } 35 input.close(); 36 37 if (collection.size() > 0) { // 判断集合中是否有元素 38 Integer[] arr = new Integer[collection.size()]; 39 collection.toArray(arr); 40 41 // 创建字符串缓冲区对象 42 StringBuffer sb = new StringBuffer("录入的整数为:{"); 43 44 for (Integer item : arr) { 45 sb.append(item + ","); 46 } 47 48 // 上述遍历操作会在最后一个元素获取放入到字符串缓冲区对象中时多添加一个逗号 49 String str = sb.substring(0, sb.length() - 1) + "}"; 50 51 // 通过Arrays类的sort方法进行排序 52 Arrays.sort(arr); 53 54 System.out.println(str + ",最大整数为:" + arr[arr.length - 1]); 55 } 56 } 57 }
1 package cn.temptation.test; 2 3 import java.util.Scanner; 4 5 import cn.temptation.model.User; 6 import cn.temptation.service.UserService; 7 import cn.temptation.service.UserServiceImpl; 8 9 public class Sample20 { 10 public static void main(String[] args) { 11 // 需求:结合集合和泛型实现一般系统都有的功能 12 // 1、注册功能:存储用户信息(用户帐号 和 用户密码) 13 // 2、登录功能:输入用户信息(帐号和密码) 和 存储的用户信息进行比较,来确定输入的用户信息是否正确,如果正确,提示登录成功;否则不给其登录系统 14 // 3、游戏功能:登录成功后可以玩猜数字的游戏(猜测从0~9之间的一个数),猜对了,提示是否还要继续玩,继续玩就继续猜数字;猜错了也提示猜错了,提示是否还要继续玩 15 // (输入Y表示继续玩,输入N表示不玩了) 16 17 // 通过分层思想,把有相同性质的操作划为一层 18 19 // 系统的数据载体:用户信息存储在用户类 20 21 System.out.println("【用户系统】"); 22 Scanner input = new Scanner(System.in); 23 24 // 注意:下句语句会带来逻辑错误,会导致注册时集合中只有一个用户信息,后续注册会覆盖之前注册的信息; 25 // 并且怎么登录都是成功,因为集合中只存储一个User对象,所以正确写法应该注册时创建不同的用户对象,登录时接受交互数据也使用不同的用户对象 26 // User user = new User(); 27 // 正确写法:只做声明,不进行初始化 28 User user; 29 30 // 调用业务逻辑处理 31 UserService service = new UserServiceImpl(); 32 33 while (true) { 34 System.out.println("----------------------------------"); 35 System.out.println("1、登录"); 36 System.out.println("2、注册"); 37 System.out.println("3、退出"); 38 39 System.out.println("根据功能菜单,输入操作指令:"); 40 41 String str = input.nextLine(); 42 user = new User(); 43 44 switch (str) { 45 case "1": // 登录处理 46 // 既然登录和注册时都需要创建用户对象,所以放在switch之外写 47 // user = new User(); 48 49 System.out.println("欢迎使用【登录功能】"); 50 51 // 接收交互数据,并封装在用户类的对象中 52 System.out.println("输入用户帐号:"); 53 user.setUsername(input.nextLine()); 54 System.out.println("输入用户密码:"); 55 user.setPassword(input.nextLine()); 56 57 if (service.login(user)) { 58 System.out.println("登录成功!"); 59 60 while (true) { 61 System.out.println("想玩猜数字的游戏么?输入Y表示想玩,输入N表示不玩"); 62 63 String flag = input.nextLine(); 64 65 if ("Y".equalsIgnoreCase(flag)) { 66 service.play(input); 67 } else if ("N".equalsIgnoreCase(flag)) { 68 break; 69 } 70 } 71 } else { 72 System.out.println("登录失败!"); 73 } 74 75 break; 76 case "2": // 注册处理 77 // 既然登录和注册时都需要创建用户对象,所以放在switch之外写 78 // user = new User(); 79 80 System.out.println("欢迎使用【注册功能】"); 81 82 // 接收交互数据,并封装在用户类的对象中 83 System.out.println("输入用户帐号:"); 84 user.setUsername(input.nextLine()); 85 System.out.println("输入用户密码:"); 86 user.setPassword(input.nextLine()); 87 88 if (service.register(user)) { 89 System.out.println("注册成功!"); 90 } 91 92 break; 93 case "3": // 退出处理 94 default: 95 System.out.println("谢谢使用!"); 96 // System类的常用成员方法: 97 // static void exit(int status) :终止当前正在运行的 Java 虚拟机。 98 System.exit(0); 99 break; 100 } 101 } 102 } 103 }
1 package cn.temptation.service; 2 3 import java.util.Scanner; 4 5 import cn.temptation.model.User; 6 7 /** 8 * 用户业务逻辑处理接口 9 */ 10 public interface UserService { 11 // 接口中方法定义的思路: 12 // 以注册为例,可以给注册方法传递两个参数 ----- 用户帐号 和 用户密码 13 // 但是考虑到如果注册业务逻辑发生了变化,比如:注册还需要加上邮箱,这样必然需要修改方法的声明,修改非常麻烦 14 // 出于封装性的考虑,直接传递一个POJO对象----- 用户实体类,封装全部用户信息,这样即使逻辑变化,方法的声明不用修改 15 16 // 用户注册 17 // public abstract boolean register(String username, String password); 18 public abstract boolean register(User user); 19 20 // 用户登录 21 public abstract boolean login(User user); 22 23 // 玩猜数字游戏 24 public abstract void play(Scanner input); 25 }
1 package cn.temptation.service; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Scanner; 6 7 import cn.temptation.model.User; 8 9 /** 10 * 用户业务逻辑处理接口的实现类 11 */ 12 public class UserServiceImpl implements UserService { 13 // 成员变量 14 // 下面两种写法效果相同 15 // 写法1、非静态的成员变量,类初始化时进行初始化,创建出集合对象 16 // Collection<User> collection = new ArrayList<>(); 17 // 写法2、静态的成员变量,类加载时就进行初始化,创建出集合对象 18 static Collection<User> collection = new ArrayList<>(); 19 20 @Override 21 public boolean register(User user) { 22 // 考虑到用户信息存储在内存中,因为注册的用户数量未知,所以选用集合进行存储 23 // Collection<User> collection = new ArrayList<>(); 24 25 // 向集合容器添加用户对象,并返回添加结果 26 return collection.add(user); 27 } 28 29 @Override 30 public boolean login(User user) { 31 // 因为登录时要判断登录录入的用户信息和集合容器中存储的用户信息是否有一致的,所以登录功能用的集合容器和注册功能用的集合容器应该一致 32 33 boolean result = false; 34 35 // 遍历容器中用户信息 36 for (User item : collection) { 37 // 帐号 和 密码均一致 38 if (item.getUsername().equals(user.getUsername()) && item.getPassword().equals(user.getPassword())) { 39 result = true; 40 // 找到有匹配的用户对象就不用再继续遍历了 41 break; 42 } 43 } 44 45 return result; 46 } 47 48 @Override 49 public void play(Scanner input) { 50 // 1、生成答案数字 51 int result = (int) (Math.random() * 10); 52 53 System.out.println("输入0~9之间的一个整数:"); 54 55 // 2、让用户猜测,并给予提示 56 for (;;) { 57 int temp = Integer.parseInt(input.nextLine()); 58 59 if (temp > result) { 60 System.out.println("猜大了!"); 61 } else if (temp < result) { 62 System.out.println("猜小了!"); 63 } else { 64 System.out.println("恭喜,猜对了!"); 65 break; 66 } 67 } 68 } 69 }
1 package cn.temptation.model; 2 3 // POJO:Plain Orinary Java Object 简单的单纯的Java对象 4 // POJO类在系统架构中,一般用作数据的载体,在系统架构的不同层之间进行数据传递(实体类) 5 /** 6 * 用户实体类 7 */ 8 public class User { 9 // 成员变量 10 // 用户帐号 11 private String username; 12 // 用户密码 13 private String password; 14 15 // 构造函数 16 public User() { 17 super(); 18 } 19 20 public User(String username, String password) { 21 super(); 22 this.username = username; 23 this.password = password; 24 } 25 26 // 成员方法 27 public String getUsername() { 28 return username; 29 } 30 31 public void setUsername(String username) { 32 this.username = username; 33 } 34 35 public String getPassword() { 36 return password; 37 } 38 39 public void setPassword(String password) { 40 this.password = password; 41 } 42 }