9.6 Random
1、Random的概述和基本使用和生成指定范围的随机数
Random类用来生成随机数字。使用起来也是三个步骤:
1.导包
import java.util.Random;
2.创建
Random r=new Random();//小括号当中留空即可
3.使用
获取一个随机的int数字(范围是int所有范围,有正负两种),int num=r.nextInt();
获取一个随机的int数字(参数代表了范围,左闭右开区间),int num=r.nextInt(10);
实际上代表的含义是:[0,10) 0-9
public class Demo01Random { public static void main(String[] args) { Random r=new Random(); int num=r.nextInt();//范围是int所有范围,有正负两种 int num1=new Random().nextInt(10);//范围在10以内 System.out.println("生成随机数:"+num); System.out.println("生成随机数:"+num1); System.out.println("================"); Random r1=new Random(); int index=0; for(int i=0;i<20;i++){ int n=r1.nextInt(5);//范围实际上是:0-4 System.out.print(" "+n); } } } 练习一:生成1-n的随机数 /* 题目要求: 根据int变量n的值,来获取随机数字,范围是[1,n],可以取到1也可以取到n. 思路: 1.定义一个int变量n,随意赋值。 2.要使用Random:三个步骤:导包,创建,使用 3.如果写10,那么就是0~9,然而想要的是1~10,可以发现:整体+1即可 4.打印随机数字 */ public class Demo02Random { public static void main(String[] args) { int n=5; Random r=new Random(); for(int i=0;i<100;i++){ int result=r.nextInt(n)+1; //本来范围是[0,n],整体+1之后变成[1,n+1],也就是[1,n] System.out.println(result); } } } 练习二: /* 题目: 用代码模拟猜数字的小游戏。 思路: 1.首先需要产生一个随机数,并且一旦产生不在变化。用Random的nextInt方法 2.需要键盘输入,所以用到了Scanner 3.获取键盘输入的数字,用Scanner当中的nextInt方法 4.已经得到两个数字,判断(if)一下 如果太大了,提示太大,并重试; 如果太小了,提示太小,并重试; 如果猜中了,游戏结束 5.重试就是再来一次,循环次数不确定用while(true) */ import java.util.Random; import java.util.Scanner; public class Demo03Random { public static void main(String[] args) { int r = new Random().nextInt(100) + 1;//[1,100] while (true) { System.out.println("输入数字:"); int x = new Scanner(System.in).nextInt(); if (x > r) { System.out.println("猜大了"); } else if(x<r){ System.out.println("猜小了"); }else{ System.out.println("恭喜猜对了"); break; } } System.out.println("结束"); } }
快捷键添加构造方法和get、set方法:将光标放到成员变量,按下快捷键Alt+Insert
9.7 ArrayList
什么是集合:
提供一种存储空间可变的存储模型,存储的数据容量可以发生改变。
ArrayList集合的特点
底层是数组实现的,长度可以变化 。
泛型的使用
用于约束集合中存储元素的数据类型。
1、ArrayList集合概述和基本使用
数组的长度不可以发生改变。
但是ArrayList集合的长度是可以随意变化的。
对于ArrayList来说,有一个尖括号代表泛型。
泛型:也就是装在集合当中的所有元素,全都是统一的什么类型。
注意:泛型只能是引用类型,不能是基本类型。
注意事项:
对于ArrayList集合来说,直接打印得到的不是地址值,而是内容。
如果内容是空,得到的是空的中括号:[]
public class arraylist01 { public static void main(String[] args) { //创建了一个ArrayList集合,集合的名称是list,里面装的全都是String字符串类型的数据 //备注:从JDK1.7+开始,右边的尖括号内部可以不写内容,但是<>本身还是要写的。 ArrayList<String> list=new ArrayList<>(); System.out.println(list);//[] //向集合当中添加一些数据,需要用到add方法。 list.add("赵丽颖"); System.out.println(list);//[赵丽颖] list.add("赵四"); list.add("张翰"); list.add("刘坤"); System.out.println(list);//[赵丽颖, 赵四, 张翰, 刘坤] //指定位置插入 list.add(2,"张宏里"); System.out.println(list);//[赵丽颖, 赵四, 张宏里, 张翰, 刘坤] } }
2、ArrayList集合的常用方法和遍历
1.ArrayList常用方法有
public boolean add(E e):向集合当中添加元素,参数的类型和泛型一致。
public E get (int index):从集合当中获取元素,参数是索引编号”下标从0开始“,返回值就是对应位置的元素。
public E remove(int index):从集合当中删除元素,参数是索引编号,返回值就是被删除掉的元素。
public int size():获取集合的尺寸长度,返回值是集合中包含的元素个数。
public class arraylist02 { public static void main(String[] args) { ArrayList<String> list=new ArrayList<>(); System.out.println(list);//[] //1.向集合中添加元素:add boolean success= list.add("柳岩"); System.out.println(list);//[柳岩] System.out.println("添加的动作成功:"+success);//true list.add("张氏"); list.add("胡歌"); list.add("张绍云"); System.out.println(list);//[柳岩, 张氏, 胡歌, 张绍云] //2.从集合中获取元素:get。索引值从0开始 String name=list.get(2); System.out.println("第2号索引位置:"+name);//胡歌 //3.从集合中删除元素:remove。索引值从0开始 String whoRemove=list.remove(3); System.out.println("被删除的人是:"+whoRemove);//张绍云 System.out.println(list);//[柳岩, 张氏, 胡歌] //4.获取集合的长度尺寸,也就是其中元素的个数 int size= list.size(); System.out.println("集合的长度是:"+size);//3 } } 2.遍历:遍历{快捷键:list.fori} public class arraylist03 { public static void main(String[] args) { ArrayList<String> list=new ArrayList<>(); list.add("赵丽颖"); list.add("胡歌"); list.add("张三"); list.add("刘涛"); list.add("刘四"); //遍历{快捷键:list.fori} for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); //遍历集合通用格式 // String s=list.get(i); // System.out.println(s); } } } 3、ArrayList集合存储基本数据类型 /* 如果希望向集合ArrayList当中存储基本类型数据,必须使用基本类型对应的”包装类“。 基本类型 包装类(引用类型,包装类都位于java.long包下) int Integer char Character byte Byte short Short long Long float Float double Double boolean Boolean 从JDK1.5+开始,支持自动装箱、自动拆箱 自动装箱:基本类型---->包装类型 自动拆箱:包装类型---->基本类型 */ public class arraylist04 { public static void main(String[] args) { ArrayList<String> listA=new ArrayList<>(); //错误写法!泛型只能是引用类型,不能是基本类型 //ArrayList<int> listB=new ArrayList<>(); ArrayList<Integer> listC=new ArrayList<>(); //向集合中添加元素:add listC.add(100); listC.add(200); System.out.println(listC);//[100, 200] //从集合中获取元素:get。索引值从0开始 int num=listC.get(1); System.out.println("第一个元素是:"+num);//200 } } 4、练习 练习一:存储随机数 /* 题目: 生成6个1~33之间的随机数,添加到集合,并遍历集合 思路: 1.需要存储6个数字,创建一个集合,<Integer> 2.产生随机数,需要用到Random 3.用循环6次,来产生6个随机数字:for循环 4.循环内调用r.nextInt(int n),参数是33,0~32,整体+1才是1~33 5.把数字添加集合中:add 6.遍历集合:for、size、get */ public class arraylist05 { public static void main(String[] args) { ArrayList<Integer> list=new ArrayList<>(); //获得随机数 for (int i = 0; i < 6; i++) { int r=new Random().nextInt(33)+1; list.add(r); } //遍历集合 for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } } 练习二:存储自定义对象 /* 题目: 自定义4个学生对象,添加到集合,并遍历 思路: 1.自定义Student学生类,四个部分。 2.创建一个集合,用来存储学生对象。泛型:<Student> 3.将4个学生对象添加到集合中:add 4.遍历集合:for、size、get */ public class arraylist07 { public static void main(String[] args) { ArrayList<Student> list=new ArrayList<>(); Student one=new Student("张翰",32); Student two=new Student("郭靖",66); Student three=new Student("张国立",72); Student four=new Student("胡歌",32); list.add(one); list.add(two); list.add(three); list.add(four); //遍历集合 for (int i = 0; i < list.size(); i++) { //System.out.println(list.get(i)); Student stu=list.get(i); System.out.println("姓名:"+stu.getName()+",龄:"+stu.getAge()); } } } public class Student { private String name; private int age; //无参构造 public Student() { } //全参构造 public Student(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } } 练习三:按指定格式遍历集合字符串 /* 题目: 定义以指定格式打印集合的方法(Arraylist类型作为参数),使用{}括起来集合,使用@分隔每个元素。 格式参照{元素@元素@元素}。 System.out.println(list); [10,20,30] printArraylist(list); {10,20,30} */ public class arraylist06 { public static void main(String[] args) { ArrayList<String> list=new ArrayList<>(); list.add("张三丰"); list.add("张无忌"); list.add("张翠山"); list.add("张晓明"); System.out.println(list); printArraylist(list); } /* 定义方法的三要素: 返回值类型:只是进行打印而已,没有运算,没有结果,所以用viod 方法名称:printArraylist 参数列表:ArrayList */ public static void printArraylist(ArrayList<String> list){ System.out.print("{"); for(int i=0;i<list.size();i++){ String name =list.get(i); if(i== list.size()-1){ System.out.println(name+"}"); }else { System.out.print(name + "@"); } } }} 练习四:筛选集合中的随机数 /* 题目: 用一个大集合存入20个随机数字,然后筛选其中的偶数元素,放到小集合当中 要求使用自定义的方法来实现筛选。 分析: 1.需要创建一个大集合,用来存储int数字:<Integer> 2.随机数就用Random nextInt 3.循环20次,把随机数字放入大集合:forx循环、add方法 4.定义一个方法,用来筛选符合要求的元素,得到小集合 筛选:根据大集合,筛选符合要求的元素,得到小集合。 三要素: 返回值类型:ArrayList小集合(里面元素个数不确定) 方法名称:getSmallList 参数列表:ArrayList大集合(装20个随机数字) 5.判断(if)是偶数:num%2==0 6.如果是偶数,就放到小集合当中。否则不放 */ public class return01 { public static void main(String[] args) { //创建了一个ArrayList集合,集合的名称是biglist,里面装的全都是int型数据 ArrayList<Integer> biglist=new ArrayList<>(); Random r=new Random(); for (int i = 0; i < 20; i++) { int num=r.nextInt(100)+1;//1~100 biglist.add(num); } ArrayList<Integer> smallList=getSmallList(biglist); System.out.println("偶数总共有:"+smallList.size()); for(int i=0;i<smallList.size();i++) { System.out.println(smallList.get(i)); } } //这个方法,接受大集合参数,返回小集合结果 public static ArrayList<Integer> getSmallList(ArrayList<Integer> biglist){ //创建一个小集合,用来装偶数结果 ArrayList<Integer> smallList=new ArrayList<>(); for(int i=0;i<biglist.size();i++){ int num=biglist.get(i); if(num%2==0){ smallList.add(num); } } return smallList; } }
十、字符串String
1、charAt(int index):返回指定索引处的 char 值。
2、indexOf(String ch):返回指定字符在此字符串中第一次出现处的索引。
3、isEmpty():当且仅当 length() 为 0 时返回 true。
4、lastIndexOf(String ch):返回指定字符在此字符串中最后一次出现处的索引。
5、length():返回此字符串的长度。
6、replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
7、split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串。
8、startsWith(String prefix):测试此字符串是否以指定的前缀开始。
9、toLowerCase():使用默认语言环境的规则将此 String 中的所有字符都转换为小写。
10、String toUpperCase():使用默认语言环境的规则将此 String 中的所有字符都转换为大写。
11、contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true。
10.1 字符串构造方法和直接创建
构造方法:
public String() 创建一个空白字符串对象,不含有任何内容
public String(char[] chs) 根据字符数组的内容,来创建字符串对象
public String(byte[] bys) 根据字节数组的内容,来创建字符串对象
String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc
public class t1 { public static void main(String[] args) { //public String():创建一个空白字符串对象,不含有任何内容 String s1=new String(); System.out.println("s1:"+s1);// //public String(char[] chs):根据字符数组的内容,来创建字符串对象 char[] chs={'a','b','c'}; String s2=new String(chs); System.out.println("s2:"+s2);//abc //public String(byte[] bys):根据字节数组的内容,来创建字符串对象 byte[] bys={97,98,99}; String s3=new String(bys); System.out.println("s3:"+s3);//abc //String s = “abc”; 直接赋值的方式创建字符串对象,内容就是abc String s4="abc"; System.out.println("s4:"+s4);//abc } }
10.2 字符串常量池
通过构造方法创建 :String s3=new String(类型);
通过 new 创建的字符串对象,每一次 new 都会申请一个内存空间,虽然内容相同,但是地址值不同直接赋值方式创建 : String s4="abc";
以“”方式给出的字符串,只要字符序列相同(顺序和大小写),无论在程序代码中出现几次,JVM 都只会建立一 个 String 对象,并在字符串池中维护
10.3 字符串方法
public StringBuilder append (任意类型) 添加数据,并返回对象本身。
public StringBuilder reverse() 返回相反的字符序列。
public int length() 返回长度,实际存储值。
public String toString() 通过toString()就可以实现把StringBuilder转换为String。
1、比较相关法
= =号的作用:
比较基本数据类型:比较的是具体的值
比较引用数据类型:比较的是对象地址值
方法介绍:比较两个字符串内容是否相同、区分大小写
public boolean equals(String s) 比较两个字符串内容是否相同、区分大小写
public boolean equals(Object anObject):将此字符串与指定对象进行比较。由于我们比较的是字符串对象,所以参数直接传递一个字符串
public class t2 { public static void main(String[] args) { //构造方法的方式得到对象 char[] chs={'a','b','c'}; String s1=new String(chs); String s2=new String(chs); System.out.println(s1);//abc System.out.println(s2);//abc System.out.println("==========="); //直接赋值的方式得到对象 String s3="abc"; String s4="abc"; //比较字符串对象【地址】是否相同 System.out.println(s1==s2);//false System.out.println(s1==s3);//false System.out.println(s3==s4);//true System.out.println("==========="); //比较字符串【内容】是否相同 System.out.println(s1.equals(s2));//true System.out.println(s1.equals(s3));//true System.out.println(s1.equals(s4));//true } }
练习 public class t3 { public static void main(String[] args) { //已知用户名和密码,定义两个字符串表示即可 String username = "heima"; String password = "1234"; //用循环实现多次机会,这里的次数明确, // 采用for循环实现,并在登录成功的时候,使用break结束循环 for (int i = 0; i < 3; i++) { //键盘录入要登录的用户名和密码,用 Scanner 实现 Scanner sc=new Scanner(System.in); System.out.println("输入用户名:"); String name=sc.nextLine(); System.out.println("输入密码:"); String pwd=sc.nextLine(); //拿键盘录入的用户名、密码和已知的用户名、密码进行比较,给出相应的提示。 // 字符串的内容比较,用equals() 方法实现 if (name.equals(username)&&pwd.equals(password)){ System.out.println("登陆成功"); break; }else{ if(2-i==0){ System.out.println("密码被锁定,请联系管理员解锁"); }else{ System.out.println("登陆失败,还有"+(2-i)+"次机会"); } } } }}
charAt(int index)方法是一个能够用来检索特定索引下的字符的String实例的方法.
charAt()方法返回指定索引位置的char值。索引范围为0~length()-1.
执行自动类型转换需要两个条件:
1、两种类型是兼容的,比如所有的数字类型都是兼容的,而数字类型和布尔类型是不兼容的
2、目的类型的范围比源类型的大。如:从int类型向float类型转换可以自动实现,反之则需要进行强制类型转换。
所谓强制类型转换实际上只是一种显示类型的转换
2、获取相关法
charAt(int index)方法是一个能够用来检索特定索引下的字符的String实例的方法.
charAt()方法返回指定索引位置的char值。索引范围为0~length()-1.
/* 思路: 1:定义一个 int 类型的数组,用静态初始化完成数组元素的初始化 2:定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。 返回值类型 String,参数列表 int[] arr 3:在方法中遍历数组,按照要求进行拼接 4:调用方法,用一个变量接收结果 5:输出结果 */ public class t6 { public static void main(String[] args) { //定义一个 int 类型的数组,用静态初始化完成数组元素的初始化 int[] a={1,2,3,4}; //调用方法,用一个变量接收结果 String s=array(a); //输出结果 System.out.println("s:"+s); } //定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回 /* 两个明确: 返回值类型:String 参数:int[] arr */ private static String array(int[] a) { //在方法中遍历数组,按照要求进行拼接 String s=" "; s=s+"["; for (int i = 0; i < a.length; i++) { if (i==a.length-1){ s=s+a[i]; } else{ s+=a[i]; s+=","; } } s=s+"]"; return s; } } 3、截取相关法 subString(int index):截取从参数位置一直到字符串末尾,返回新字符串。 /* 字符串的截取方法: public String subString(int index):截取从参数位置一直到字符串末尾,返回新字符串。 public String subString(int index,int end):截取从begin开始,一直到end结束,中间的字符串。 备注: [index,end),包含左边,不包含右边。 */ public class t3 { public static void main(String[] args) { String str1="HelloWord"; String str2=str1.substring(5); System.out.println(str1);//HelloWord System.out.println(str2);//Word System.out.println("==========="); //下面这种写法,字符串的内容仍然是没有改变的 //下面有两个字符串:"hello" "java" //str中保存的是地址值 //本来地址值是hello中的地址0x66 //后来地址值变成了0x999 String strA= "hello" ; System.out.println(strA);//hello strA="java"; System.out.println(strA);//java } } 4、转换相关法 /* String 当中与转换相关的常用方法 public char[] toCharArray():将当前字符串拆分成为字符数组作为返回值。 public byte[] getBytes():获得当前字符串底层的字节数组。 public String[] replace(CharSequence oldString,CharSequence newString); 将所有出现的老字符串替换成新的字符串,返回替换之后的结果新字符串。 备注:CharSequence意思就是说可以接受字符串类型 */ public class t4 { public static void main(String[] args) { //转换成为字符数组 char[] chars = "Hello".toCharArray(); System.out.println(chars[0]);//H System.out.println(chars.length);//5 System.out.println("============="); //转换成为字节数组 byte[] bytes = "abc".getBytes(); for (int i = 0; i < bytes.length; i++) { System.out.println(bytes[i]); } System.out.println("=========="); //字符串的内容转换 String str1 = "How do you do"; String str2 = str1.replace("o", "*"); System.out.println(str1);//How do you do System.out.println(str2);//H*w d* y*u d* String lang1 = "会不会玩,会不会玩,你大爷的!你大爷的!"; String lang2=lang1.replace("你大爷的","****"); System.out.println(lang2);//会不会玩,会不会玩,****!****! //System.out.println(lang1); } } /* 思路: 1:键盘录入一个字符串,用 Scanner 实现 2:定义一个方法,实现字符串反转。返回值类型 String,参数 String s 3:在方法中把字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并返回 4:调用方法,用一个变量接收结果 5:输出结果 */ import java.util.Scanner; public class t1 { public static void main(String[] args) { //键盘录入一个字符串,用 Scanner 实现 System.out.println("请输入你要输入的数字:"); String line=new Scanner(System.in).nextLine(); //调用方法,用一个变量接收结果 String s=reverse(line); //输出结果 System.out.println("s:"+s); } //定义一个方法,实现字符串反转 /* 两个明确: 返回值类型:String 参数:String s */ private static String reverse(String s) { //在方法中把字符串倒着遍历,然后把每一个得到的字符拼接成一个字符串并返回 String ss=" "; for (int i=s.length()-1;i>=0; i--) { ss=ss+s.charAt(i); } return ss; } } public boolean equals(Object anObject) 比较字符串的内容,严格区分大小写(用户名和密码) public char charAt(int index) 返回指定索引处的 char 值 public int length() 返回此字符串的长度 StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的 内容是可变的。 String类:内容是不可变的 StringBuilder类:内容是可变的 public StringBuilder() 创建一个空白可变字符串对象,不含有任何内容 public StringBuilder(String str) 根据字符串的内容,来创建可变字符串对象 5、分割相关法 /* 分割字符串的方法: public String[] split(String regex):按照参数的规则,将字符串分割成为若干部份。 注意事项: split方法的参数其实是一个正则表达式,今后学习。 今天要注意:如果按照英文据点“.”进行分割,必须写“\\.” */ public class t5 { public static void main(String[] args) { String str1="aaa,bbbb,ssss"; String[] array1=str1.split(","); for (int i = 0; i <array1.length ; i++) { System.out.println(array1[i]); } System.out.println("============"); String str2="aaaaa aaaa ssssss"; String[] array2=str2.split(" "); for (int i = 0; i < array2.length; i++) { System.out.println(array2[i]); } System.out.println("============"); String str3="aaaaa.aaaa.ssssss"; String[] array3=str3.split("\\."); for (int i = 0; i < array3.length; i++) { System.out.println(array3[i]); } } }
StringBuilder类
public StringBuilder append (任意类型) 添加数据,并返回对象本身
public StringBuilder reverse() 返回相反的字符序列
public int length() 返回长度,实际存储值
public String toString() 通过toString()就可以实现把StringBuilder转换为String
StringBuilder 是一个可变的字符串类,我们可以把它看成是一个容器,这里的可变指的是 StringBuilder 对象中的 内容是可变的。
常用的构造方法
public StringBuilder(): 创建一个空白可变字符串对象,不含有任何内容
public StringBuilder(String str) :根据字符串的内容,来创建可变字符串对象
public class StringBuilderDemo01 { public static void main(String[] args) { //public StringBuilder():创建一个空白可变字符串对象,不含有任何内容 StringBuilder sb = new StringBuilder(); System.out.println("sb:" + sb); System.out.println("sb.length():" + sb.length()); //public StringBuilder(String str):根据字符串的内容,来创建可变字符串对象 StringBuilder sb2 = new StringBuilder("hello"); System.out.println("sb2:" + sb2); System.out.println("sb2.length():" + sb2.length()); } }
StringBuilder类添加和反转方法
添加和反转方法
public StringBuilder append(任意类型): 添加数据,并返回对象本身
public StringBuilder reverse() :返回相反的字符序列
public class StringBuilderDemo01 { public static void main(String[] args) { //创建对象 StringBuilder sb = new StringBuilder(); //public StringBuilder append(任意类型):添加数据,并返回对象本身 // StringBuilder sb2 = sb.append("hello"); // // System.out.println("sb:" + sb); // System.out.println("sb2:" + sb2); // System.out.println(sb == sb2); // sb.append("hello"); // sb.append("world"); // sb.append("java"); // sb.append(100); //链式编程 sb.append("hello").append("world").append("java").append(100); System.out.println("sb:" + sb); //public StringBuilder reverse():返回相反的字符序列 sb.reverse(); System.out.println("sb:" + sb); } }
StringBuilder和String相互转换
StringBuilder转换为String
public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String
String转换为StringBuilder
public StringBuilder(String s):通过构造方法就可以实现把 String 转换为 StringBuilder
public class StringBuilderDemo02 { public static void main(String[] args) { /* //StringBuilder 转换为 String StringBuilder sb = new StringBuilder(); sb.append("hello"); //String s = sb; //这个是错误的做法 //public String toString():通过 toString() 就可以实现把 StringBuilder 转换为 String String s = sb.toString(); System.out.println(s); */ //String 转换为 StringBuilder String s = "hello"; //StringBuilder sb = s; //这个是错误的做法 //public StringBuilder(String s):通过构造方法就可以实现把 String 转换为StringBuilder StringBuilder sb = new StringBuilder(s); System.out.println(sb); } } 字符串拼接升级版案例 /* 思路: 1:定义一个 int 类型的数组,用静态初始化完成数组元素的初始化 2:定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回。 返回值类型 String,参数列表 int[] arr 3:在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回 4:调用方法,用一个变量接收结果 5:输出结果 */ public class StringBuilderTest01 { public static void main(String[] args) { //定义一个 int 类型的数组,用静态初始化完成数组元素的初始化 int[] arr = {1, 2, 3}; //调用方法,用一个变量接收结果 String s = arrayToString(arr); //输出结果 System.out.println("s:" + s); } //定义一个方法,用于把 int 数组中的数据按照指定格式拼接成一个字符串返回 /* 两个明确: 返回值类型:String 参数:int[] arr */ public static String arrayToString(int[] arr) { //在方法中用 StringBuilder 按照要求进行拼接,并把结果转成 String 返回 StringBuilder sb = new StringBuilder(); sb.append("["); for(int i=0; i<arr.length; i++) { if(i == arr.length-1) { sb.append(arr[i]); } else { sb.append(arr[i]).append(", "); } } sb.append("]"); String s = sb.toString(); return s; } } 定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果 例如,键盘录入abc,输出结果 cba /* 思路: 1:键盘录入一个字符串,用 Scanner 实现 2:定义一个方法,实现字符串反转。返回值类型 String,参数 String s 3:在方法中用StringBuilder实现字符串的反转,并把结果转成String返回 4:调用方法,用一个变量接收结果 5:输出结果 */ public class StringBuilderTest02 { public static void main(String[] args) { //键盘录入一个字符串,用 Scanner 实现 Scanner sc = new Scanner(System.in); System.out.println("请输入一个字符串:"); String line = sc.nextLine(); //调用方法,用一个变量接收结果 String s = myReverse(line); //输出结果 System.out.println("s:" + s); } //定义一个方法,实现字符串反转。返回值类型 String,参数 String s /* 两个明确: 返回值类型:String 参数:String s */ public static String myReverse(String s) { //在方法中用StringBuilder实现字符串的反转,并把结果转成String返回 //String --- StringBuilder --- reverse() --- String // StringBuilder sb = new StringBuilder(s); // sb.reverse(); // String ss = sb.toString(); // return ss; return new StringBuilder(s).reverse().toString(); } }
10.4 静态static
1、静态static关键字修饰成员变量
public class Student { private int id; private String name; private int age; static String room ; private static int idCounter=0;//学号计数器,每当new了一个新对象的时候,计数器++ public Student() { idCounter++; } public Student(int id) { this.id = id; } public int getId() { return id; } public void setId(int id) { this.id = id; } public Student(String name, int age) { this.name = name; this.age = age; this.id=++idCounter; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } /* 如果一个变量使用了static关键字,那么这个变量不在属于对象自己,而是属于所在的类。多个对象共享同一份数据 */ public class Demo01Static { public static void main(String[] args) { Student two=new Student("黄蓉",16); two.room="001教室"; System.out.println("姓名:"+two.getName()+",学号:"+two.getId() +",年龄:"+two.getAge()+", 教室:"+two.room); Student one=new Student("郭靖",18); System.out.println("姓名:"+one.getName()+",学号:"+one.getId() +",年龄:"+one.getAge()+", 教室:"+one.room); // Student two=new Student("黄蓉",16); // two.room="001教室"; // System.out.println("姓名:"+two.getName()+",学号:"+two.getId() // +",年龄:"+two.getAge()+", 教室:"+two.room); } }
2、静态static关键字修饰成员方法
/* 一旦使用static修饰成员方法,那么这就成为了静态方法。静态方法不属于对象,而是属于类的。 如果没有static关键字,那么必须首先创建对象,然后通过对象才能使用它。 如果有static关键字,那么不需要创建对象,直接就能通过类名称来使用它。 无论是成员变量,还是成员方法。如果有了static,都推荐按使用类名称进行调用。 静态变量:类名称.静态变量 静态方法:类名称.静态方法() 注意事项: 1.静态不能直接访问非静态。 原因:因为在内存中是【先】有的静态内容,【后】有的非静态内容 ”先人不知道后人,但是后人知道先人“ 2.静态方法当中不能用this 原因:this代表当前对象,通过谁调用的方法,谁就是当前对象 */ public class Demo02myclass { public static void main(String[] args) { MyClass obj=new MyClass();//创建对象 //然后才能使用没有static关键字的内容 obj.method(); //对于静态方法来说,可以通过对象名进行调用,,也可以直接通过类名称来调用 obj.methodStatic();//正确,不推荐 MyClass.methodStatic();//正确,推荐 //对于本来当中的静态方法,可以省略类名称 myMethod(); Demo02myclass.myMethod();//完全等效 } private static void myMethod() { System.out.println("自己的方法"); } } public class MyClass { int num;//成员变量 static int numStatic;//静态变量 //成员方法 public void method(){ System.out.println("这是一个成员方法"); //成员方法可以访问成员变量 System.out.println(num); //成员方法可以访问静态变量 System.out.println(numStatic); } public static void methodStatic(){ System.out.println("这是一个静态方法"); //静态方法可以访问静态变量 System.out.println(numStatic); //静态不能直接访问非静态【重点】 //System.out.println(num);//错误方法 //静态方法中不能使用this System.out.println(this);//错误写法 } }
/* 静态代码块的格式是: public class 类名称{ static{ //静态代码块的内容 } } 特点:当第一次用到本类是,静态代码块执行唯一的一次 静态内容总是优先于非静态,所以静态代码块比构造方法先执行. 静态代码块典型用途: 用来一次性地对非静态变量赋值。 */ public class t6 { public static void main(String[] args) { Person one =new Person(); Person two =new Person(); } } public class Person { static{ System.out.println("静态代码块执行"); } public Person(){ System.out.println("构造方法执行!"); } }
10.5 数组工具类Arrays
/* java.util.Arrays是一个与数组相关的工具类,里面提供了大量静态方法,用来实现数组常见的操作。 public static String toString(数组):将参数数组变成字符串(按照默认格式:[元素1,元素2,。。。。]) public static void sort(数组):按照默认升序(从小到大)对数组的元素进行排序。 备注: 1.如果是数值,sort默认按照升序从小到大。 2.如果是字符串,sort默认按照字母升序。 3.如果是自定义的类型,那么这个定义的类型需要用Comparable或者Comparator接口的支持。(今后学习) 4. */ public class t7 { public static void main(String[] args) { int [] array={10,20,30}; //将int[]数组按照默认格式变成字符串 String str= Arrays.toString(array); System.out.println(str);//[10, 20, 30] int[] array1={2,3,4,5,9}; Arrays.sort(array1); System.out.println(Arrays.toString(array1));//[2, 3, 4, 5, 9] } }
10.6 数学工具类Math
/* java.util.Math类是数学相关的工具类,里面提供了大量的静态方法,完成与数学运算相关的操作 public static double abs(double num):获取绝对值 public static double ceil(double num):向上取整 public static double floor(double num):向下取整 public static long round(double num):四舍五入 Math.PI:代表近似的圆周率常量。 */ public class t8 { public static void main(String[] args) { //获取绝对值 System.out.println(Math.abs(3.14));//3.14 System.out.println(Math.abs(0));//0 System.out.println(Math.abs(-0.52));//0.52 System.out.println("============="); //向上取整 System.out.println(Math.ceil(3.9));//4.0 System.out.println(Math.ceil(3.1));//4.0 System.out.println("============="); //向下取整 System.out.println(Math.floor(3.9));//3.0 System.out.println(Math.floor(3.1));//3.0 System.out.println("============="); //四舍五入 System.out.println(Math.round(3.5));//4 System.out.println(Math.round(3.1));//3 } }
十一、继承
继承的概念
继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及 追加属性和方法
11.1 继承的格式
继承通过extends实现
格式:class 子类 extends 父类 { }
举例:class Dog extends Animal { }
继承带来的好处
继承可以让类与类之间产生关系,子父类关系,产生子父类后,子类则可以使用父类中非私有的成员。
11.2 继承中成员变量的访问
public class Fu { public void show(){ System.out.println("show方法调用"); } } public class Zi extends Fu{ public void method(){ System.out.println("method方法调用"); } } public class Demo01ExtendsFile { public static void main(String[] args) { //创建对象,调用方法 Fu f=new Fu(); f.show();//只调用父类对象,没有任何子类内容 Zi z=new Zi(); z.method();//method方法调用 z.show();//show方法调用 } }
11.3 区分子类方法中重名的三种变量
this:代表本类对象的引用
super:代表父类存储空间的标识(可以理解为父类对象引用)
成员变量:
this.成员变量 - 访问本类成员变量
super.成员变量 - 访问父类成员变量 成员方法: this.成员方法 - 访问本类成员方法
super.成员方法 - 访问父类成员方法
构造方法:
this(…) - 访问本类构造方法
super(…) - 访问父类构造方法
/*
局部变量: 直接写成员变量名
本类的成员变量: this.成员变量名
父类的成员变量: super.成员变量名
*/
public class Fu { int num=10; } public class Zi extends Fu{ int num=20; public void method(){ int num=30; System.out.println(num);//30,局部变量 System.out.println(this.num);//20,本类的成员变量 System.out.println(super.num);//10,父类的成员变量 } } public class Demo04 { public static void main(String[] args) { Zi zi=new Zi(); zi.method(); } }
11.4 继承中成员方法的访问特点
/*
在父子类的继承关系当中,创建子类对象,访问成员方法的规则:
创建的对象是谁,就优先用谁,如果没有则向上找。
注意事项:
无论是成员方法还是成员变量,如果没有都是向上找父类,绝对不会向下找子类的。
重写(Override)
概念:在继承关系当中,方法的名称一样,参数列表也一样。
重写(Override):方法的名称一样,参数列表【也一样】。覆盖、覆写
重写(Overload):方法的名称一样,参数列表【不一样】。
方法的覆盖重写特点:创建的是子类对象,则优先用子类方法。
*/
public class Fu { public void methodFu(){ System.out.println("父类方法执行!"); } } public class Zi extends Fu{ public void methodZi() { System.out.println("子类方法执行"); } public void method() { System.out.println("子类重名方法执行"); } } public class Demo05 { public static void main(String[] args) { Zi zi=new Zi(); zi.methodFu(); zi.methodZi(); //创建的是new了子类对象,所以优先用子类方法 zi.method(); } }
11.5 继承中方法的覆盖重写
方法覆盖重写的注意事项:
1.必须保证父子类之间方法的名称,参数列表也相同
@Override:写在方法前面,用来检测是不是有效的正确覆盖重写
这个注释就算不写,只要满足要求,也是正确的方法覆盖重写
2.子类方法的返回值必须【小于等于】父类方法的返回值范围。
前提:java.lang.Object类是所有类的公共最高父类(祖宗类),
java.lang.String就是Object的子类
3.子类方法的权限必须【大于等于】父类方法的权限修饰符。
小扩展提示:public > protected > (default) > private
备注:(default)不是关键字default,而是什么都写,留空
public class Fu { public Object method(){ return null; } } public class Zi extends Fu{ @Override public Object method(){ return null; } } public class demo06Override { public static void main(String[] args) { } }
//老款手机 public class Phone { public static void call(){ System.out.println("打电话"); } public static void send(){ System.out.println("发短信"); } public void show(){ System.out.println("显示号码"); } } //定义一款新手机,使用老手机作为父类 public class NewPhone extends Phone{ @Override public void show() { //把父类的show方法拿过来 super.show(); System.out.println("显示号码"); System.out.println("显示姓名"); System.out.println("显示头像"); } } public class Demo06Phone { public static void main(String[] args) { Phone phone=new Phone(); phone.call(); phone.send(); phone.show(); System.out.println("=========="); NewPhone newPhone=new NewPhone(); newPhone.call(); newPhone.send(); newPhone.show(); } }
11.6 继承中构造方法的访问特点
/*
继承关系中,父子类构造方法的访问特点:
1.子类构造方法中有一个默认隐含的super()调用,所以一定是先调用的父类构造,后执行的是子类构造。
2.子类构造可以通过super关键字来子类构造调用父类重载构造。
3.super的父类构造调用,必须是子类构造方法的第一个语句,不能一个子类构造调用多次super构造。
总结:
子类必须调用父类构造方法,不写则赠送super();写了则用写的指定的super调用,super只能有一个,还必须是第一个
*/
public class Fu { public Fu(){ System.out.println("父类无参构造"); } public Fu(int num){ System.out.println("父类构造方法!"); } public class Zi extends Fu{ public Zi(){ //super();//再调用父类无参构造方法 super(20); System.out.println("子类构造方法!"); } public void method(){ //super();//错误写法!只有子类构造方法,才能调用父类构造方法 } } public class Demo07 { public static void main(String[] args) { Zi zi=new Zi(); } }
11.7 super关键字三种用法
/* super关键字的用法有三种: 1.在子类的成员方法中,访问父类的成员变量。 2.在子类的成员方法中,访问父类的成员方法 3.在子类的构造方法中,访问父类的构造方法 */ public class Zi extends Fu{ int num=20; public Zi(){ super(); } public void methodZi(){ System.out.println(super.num);//父类中的num } public void method(){ super.method();//访问父类 System.out.println("子类方法"); } public class Fu { int num=10; public void method(){ System.out.println("父类方法"); } }
11.8 this关键字三种用法
super关键字用来访问父类内容,而this关键字用来访问本类内容。用法三种:
1.在本类的成员方法中,访问本类的成员变量.
2.在本类的方法中,访问本来的另一个成员方法
3.在本类的构造方法中,访问本类的另一个构造方法
在第三种用法当中要注意:
A.this(...)调用也必须是构造方法的第一个语句,唯一一个。
B.super和this两种构造方法,不能同时使用。
public class Zi extends Fu{ int num=19; public Zi(){ //super();//这一行不再赠送 this(20);//本类中的无参构造,调用本类的有参构造 //this(1,2);//错误写法 } public Zi(int n){ } public Zi(int n,int m){ } public void showNum(){ int num=20; System.out.println(num);//局部变量 System.out.println(this.num); System.out.println(super.num); } public void methodA(){ System.out.println("aaaaaa"); } public void methodB() { this.methodA(); System.out.println("bbbb"); } } public class Fu { int num=10; public void method(){ System.out.println("父类方法"); } } public class Zi extends Fu{ int num=20; @Override public void method(){ super.method();//调用父类方法 System.out.println("子类方法"); } public void show(){ int num=30; System.out.println(num);//30 System.out.println(this.num);//20 System.out.println(super.num);//10 } } public class demo { public static void main(String[] args) { Zi zi=new Zi(); zi.show(); zi.method(); } } 1.第一步运行main,然后是方法。 2.new都在对当中。
11.9 Java继承的三个特点
Java语言是单继承的。
一个类的直接父类只能有唯一一个。
11.10 抽象
1、抽象方法和抽象类的格式
/*
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束.
抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可。
如何使用抽象类和抽象对象:
1.不能直接创建new抽象类对象。
2.必须用一个子类来继承抽象父类。
3.子类必须覆盖重写抽象父类当中所有的抽象方法。
覆盖重写(实现):子类去掉抽象方法的abstract关键字,然后补上方法体大括号。
*/
public abstract class Animal { //这是一个抽象方法,代表吃的东西,但是具体吃什么(大括号的内容)不确定。 public abstract void eat(); //这是普通的成员方法 // public void method(){ //} } public class demo11 { public static void main(String[] args) { Cat cat=new Cat(); cat.eat(); } } public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } } 2、抽象方法和抽象类的使用 public class Zi extends Fu{ public Zi(){ System.out.println("子类构造方法执行!"); } //Alt+回车:自动生成 @Override public void eat() { System.out.println("吃饭饭"); } } public abstract class Fu { public Fu(){ System.out.println("抽象父类构造方法执行!"); } public abstract void eat(); } public class demo12 { public static void main(String[] args) { Zi zi=new Zi(); zi.eat(); } } 3、抽象方法和抽象类的注意事项 public class User { private String name; private int money; public User(){ } public User(String name,int money){ this.name=name; this.money=money; } //显示一下当前用户有多少钱 public void show(){ System.out.println("我叫:"+name+",我有多少钱:"+money); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getMoney() { return money; } public void setMoney(int money) { this.money = money; } } //群主类 public class Manager extends User { public Manager() { //super(); //默认在里面 } public Manager(String name, int money) { super(name, money); } //ArrayList:数组列表 ; Integer:整数 public ArrayList<Integer> send(int totalMoney, int count) { //首先需要一个集合,用来存储若干个红包的金额 ArrayList<Integer> redList = new ArrayList<>(); //首先看一下群主自己有多少钱 int leftMoney = super.getMoney();//群主当前余额 if (totalMoney > leftMoney) { System.out.println("余额不足"); return redList;//返回空集合 } //扣钱,其实就是重新设置余额 super.setMoney(leftMoney - totalMoney); //发红包需要平均分成count份 int avg = totalMoney / count; int mod = totalMoney % count;//余数,也就是甩下的零头 //出不开的零头,包在最后一个红包当中 //下面把红包一个一个放到集合当中 for (int i = 0; i < count-1; i++) { redList.add(avg); //System.out.println(); } //最后一个红包 int last=avg+mod; redList.add(last); return redList; } } //普通成员 public class Member extends User{ public Member() { } public Member(String name, int money) { super(name, money); } public void receive(ArrayList<Integer> list){ //从多个红包当中随便抽取一个,给自己 //随机获取一个集合当中的索引编号 int index=new Random().nextInt(list.size()); //根据索引,从集合当中删除,并得到被删除的红包,给自己 int delta=list.remove(index); //当前成员自己本来有多少钱 int money=super.getMoney(); //加法,并且重新设置回去 super.setMoney(money+delta); } } public class RedMain { public static void main(String[] args) { Manager manager=new Manager("群主",100); Member one=new Member("成员A",0); Member two=new Member("成员B",0); Member three=new Member("成员C",0); manager.show();//100 one.show();//0 two.show();//0 three.show();//0 System.out.println("=========="); //群主总共发20块钱,分成3个红包 ArrayList<Integer> redList=manager.send(20,3); //三个普通成员收红包 one.receive(redList); two.receive(redList); three.receive(redList); manager.show();//100-20=80 //6,6,8随机分成三人 one.show(); two.show(); three.show(); } }
十二、接口
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。
Java中的接口更多的体现在对行为的抽象!
基础知识:
1.类继承(extends)类,接口继承接口,类实现(implements)接口
2.接口没有方法体,只能声明函数
3.一个类可以实现多个接口,只能继承一个类
4.类必须重写接口的所有方法,不必须重写父类的所有方法
5.复杂关系:若接口A extends 接口B(根据1),则接口A不必须重写接口B(根据4)。
若类a implements A,则a必须要重写接口A和接口B所有的方法
若类b implements B,类a extends 类b,所以a的父类b已经实现了B的所有方法,那么a只必须要重写A的所有方法就可以了
举例:
接口A——UserService 类a——UserServiceImpl
接口B——BaseDao 类b——AbstractDao
12.1 接口的定义基本格式
接口用关键字interface修饰
备注:换成了关键字interface之后,编译生成的字节码文件仍然是:抽象方法。
java 7,接口包含内容
1.常量
2.抽象方法
java 8,接口额外包含内容
3.默认方法
4.静态方法
java 9,接口额外包含内容
5.私有方法
接口使用步骤:
1.接口不能直接使用,必须有一个“实现类”来“实现”该接口
格式:
public class 类名 implements 接口名 {}
2.接口的实现类必须覆盖重写(实现)接口中所有的抽象方法
实现:去掉abstract关键字,加上方法体大括号。
3.创建实现类的对象,进行使用
注意事项:
如果实现类并没有覆盖重写接口中所有的抽象方法,那么这个实现类自己就必须是抽象类。
public interface 接口名 { //接口内容 }
类实现接口用implements表示
public class 类名 implements 接口名 {}