常用API Random 随机数Random的介绍 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 1. 概念: java.util.Random类就是用来产生随机数字的,也是一种引用类型2. 随机数Random类的使用步骤: 和Scanner的使用步骤是相同的 (1 )导包(找到我们要使用的东西) 格式: import 包名.类名; import java.util.Random; 快捷键: alt + 回车 注意: a.java.lang包下的东西可以直接使用,不用导包 b.当前类和要使用的类,处于同一个包中,也不用导包 (2 )创建对象 类名 对象名 = new 类名(...); 类名: 之前写代码时,class关键字后面的名称 创建Scanner类的对象: Scanner sc = new Scanner (System.in); 创建Random类的对象: Random r = new Random (); (3 )使用 Scanner中获取键盘录入的整数: int num = sc.nextInt(); Random中产生随机整数数字: r.nextInt(): 产生一个int 范围内(正负21 亿)的随机数字 r.nextInt(int 类型整数数字n): 产生一个0 到n之间的随机数字(包含0 ,但是不包含n) 其中: 圆括号()中的int 类型整数数字n表示产生随机数字的上限范围 3. 练习: (1 )产生10 个int 范围内的整数数字 (2 )产生10 个0 到100 之间(包含0 ,但是不包含100 )的整数数字 (3 )产生10 个1 到100 之间(包含1 ,包含100 )的整数数字 [1 ,100 ] --> [0 ,99 ] + 1 --> [0 ,100 ) + 1 --> r.nextInt(100 ) + 1 思考: 产生10 个66 到178 之间(包含66 ,包含178 )的整数数字
Random类的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 练习: (1 )产生10 个int 范围内的整数数字 (2 )产生10 个0 到100 之间(包含0 ,但是不包含100 )的整数数字 (3 )产生2 个1 到5 之间(包含1 ,包含5 )的整数数字 (4 )产生10 个1 到100 之间(包含1 ,包含100 )的整数数字 public class Demo01Random { public static void main (String[] args) { Random r = new Random (); for (int i = 0 ; i < 10 ; i++) { int num = r.nextInt(); System.out.println(num); } System.out.println("---------------" ); for (int i = 0 ; i < 10 ; i++) { int num = r.nextInt(100 ); System.out.println(num); } System.out.println("---------------" ); for (int i = 0 ; i < 2 ; i++) { int num = r.nextInt(5 ) + 1 ; System.out.println(num); } System.out.println("---------------" ); for (int i = 0 ; i < 10 ; i++) { int num = r.nextInt(100 ) + 1 ; System.out.println(num); } System.out.println("---------------" ); while (true ) { int num = r.nextInt(100 ) + 1 ; System.out.println(num); if (num == 1 || num == 100 ) { break ; } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class Demo02Random { public static void main (String[] args) { Random r = new Random (); for (int i = 0 ; i < 10 ; i++) { int num = r.nextInt(113 )+66 ; System.out.println(num); } System.out.println("-------------" ); while (true ) { int num = r.nextInt(113 )+66 ; System.out.println(num); if (num == 66 || num == 178 ) { break ; } } } }
Random练习-猜数字 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 1. 需求:程序自动生成一个1 -100 之间(包含1 ,包含100 )的数字,使用程序实现猜出这个数字是多少? 2. 效果: 如果猜的数字比真实数字大,提示你猜的数据大了 如果猜的数字比真实数字小,提示你猜的数据小了 如果猜的数字与真实数字相等,提示恭喜你猜中了 3. 使用的知识点: (1 )使用产生随机数字的Random类(1. 导包 2. 创建对象 3. 使用: nextInt(100 )+1 ) (2 )使用键盘录入Scanner类(1. 导包 2. 创建对象 3. 使用: nextInt()) (3 )使用if 语句的第三种格式,比较用户输入的数字和产生的随机数字的大小关系 (4 )用户多少次可以猜对,不确定,需要使用循环(死循环: while (true )) (5 )用户猜测正确后,需要停止循环,使用break 4. 实现步骤: (1 )创建产生随机数字的Random类的对象 (2 )产生一个[1 ,100 ]之间的随机数字,保存到int 变量guessNum中,以供用户猜测 (3 )创建键盘录入Scanner类的对象 (4 )以下步骤(5 )-(6 )是一个循环过程,因为用户多少次可以猜对,并不能确定,使用while (true ) (5 )获取用户猜测的通过键盘录入的数字,保存到int 变量inputNum中 (6 )使用if 语句的第三种个,对用户猜测的保存在inputNum中的数字 和 产生的保存在guessNum中的数字进行比较 a.如果 inputNum 大于 guessNum 提示"你猜的数据大了" b.否则,如果 inputNum 小于 guessNum 提示"你猜的数据小了" c.否则,如果 inputNum 等于 guessNum 提示"恭喜你猜中了" ,并使用break 结束循环 注意: inputNum 等于 guessNum 条件 省略不写
图解分析:
实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class Demo03GuessNum { public static void main (String[] args) { Random r = new Random (); int guessNum = r.nextInt(100 ) + 1 ; Scanner sc = new Scanner (System.in); while (true ) { System.out.println("请输入您猜测的数字(1-100之间的整数):" ); int inputNum = sc.nextInt(); if (inputNum > guessNum) { System.out.println("你猜的数据大了" ); } else if (inputNum < guessNum) { System.out.println("你猜的数据小了" ); } else { System.out.println("恭喜你猜中了" ); break ; } } } }
Scanner 键盘录入的基本使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 数据输出: 把程序运行的结果数据输出到控制台,从而显示到屏幕上 数据输入: 获取用户从键盘上录入的数据到程序当中,然后程序根据业务需求,对获取到的数据进行相关处理 思考1 : 像数据输入这样的操作使用非常频繁,而且实现起来比较复杂,jdk的开发人员已经把此功能实现好了 jdk中把获取键盘录入数据的功能放到了java.util包的Scanner类中 思考2 : 如何使用键盘录入Scanner类呢? java中的数据类型: 基本数据类型(四类八种)和引用数据类型(类,接口,数组,枚举...) 对于引用类型的使用有固定的使用步骤,而键盘录入Scanner类就是一个引用类型,使用也有固定的步骤 键盘录入Scanner的使用,有固定的3 个步骤: ----固定格式,先记住 1. 导包(找到我们要使用的东西,告诉jvm我们使用的东西在哪里) 格式: import 包名.类名; import java.util.Scanner; 2. 创建对象: 格式: 类名 对象名 = new 类名(...); 类名: 就是之前写代码时class关键字后面的名字 Scanner sc = new Scanner (System.in); 注意: System.in是固定写法,后面就业班专门讲解 3. 使用: sc.nextInt(): 获取键盘录入的整数数字 4. 练习: 获取键盘录入的一个int 数字并输出到控制台 (1 )导包: import java.util.Scanner; (2 )创建对象: Scanner sc = new Scanner (System.in); (3 )获取键盘录入的数字: sc.nextInt() import java.util.Scanner; public class Demo01Scanner { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("哥们,请您输入一个整数数字: " ); int num = sc.nextInt(); System.out.println("您输入的整数数字: " +num); } }
键盘录入的理解
键盘录入的练习 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 需求: 获取键盘录入的两个整数(int 类型)数字,在控制台输出求和的结果。 实现步骤: 1. 导包: import java.util.Scanner 2. 创建键盘录入Scanner类的对象: Scanner sc = new Scanner (System.in) 3. 获取键盘录入的两个整数数字,分别保存到int 变量a和b中 4. 计算a和b的和,保存到int 变量sum中 5. 打印sum的值 public class Demo02ScannerSum { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入第一个整数数字: " ); int a = sc.nextInt(); System.out.println("请输入第二个整数数字: " ); int b = sc.nextInt(); System.out.println(a+"...." +b); int sum = a + b; System.out.println("和: " +sum); } }
键盘录入改写三个和尚案例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 需求: 一座寺庙里住着三个和尚,已知他们的身高分别为150cm、210cm、165cm,身高需要使用键盘录入 请用程序实现获取这三个和尚的最高身高。 实现步骤: 1. 创建键盘录入Scanner类的对象(不用单独先自己写导包) (1 )写出单词Scanner,然后按alt + / 根据提示选择相应的类 会自动导包 (2 )一边写,根据提示直接选择相应的类,回车会自动导包 2. 获取键盘录入的三个整数数字,分别代表三个和尚的身高,分别保存到int 变量h1,h2,h3中 3. 使用三元运算符求出h1和h2的最大身高,保存到int 变量temp中 4. 使用三元运算符求出temp和h3的最大身高,保存到int 变量max中 5. 打印max的值 import java.util.Scanner; public class Demo03ScannerMax { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入第一个和尚的身高(整数数字): " ); int h1 = sc.nextInt(); System.out.println("请输入第二个和尚的身高(整数数字): " ); int h2 = sc.nextInt(); System.out.println("请输入第三个和尚的身高(整数数字): " ); int h3 = sc.nextInt(); System.out.println(h1 + "..." + h2 + "..." + h3); int temp = (h1 > h2) ? h1 : h2; int max = (temp>h3) ? temp : h3; System.out.println("三个和尚的最大身高: " +max); } }
String String类概述 String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象。String 类在 java.lang 包下,所以使用的时候不需要导包!
String类的特点
字符串不可变,它们的值在创建后不能被更改
虽然 String 的值是不可变的,但是它们可以被共享
字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )
String类的构造方法
常用的构造方法
方法名
说明
public String()
创建一个空白字符串对象,不含有任何内容
public String(char[] chs)
根据字符数组的内容,来创建字符串对象
public String(byte[] bys)
根据字节数组的内容,来创建字符串对象
String s = “abc”;
直接赋值的方式创建字符串对象,内容就是abc
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class StringDemo01 { public static void main (String[] args) { String s1 = new String (); System.out.println("s1:" + s1); char [] chs = {'a' , 'b' , 'c' }; String s2 = new String (chs); System.out.println("s2:" + s2); byte [] bys = {97 , 98 , 99 }; String s3 = new String (bys); System.out.println("s3:" + s3); String s4 = "abc" ; System.out.println("s4:" + s4); } }
创建字符串对象两种方式的区别
字符串的比较 ==号的作用
比较基本数据类型:比较的是具体的值
比较引用数据类型:比较的是对象地址值
equals方法的作用
方法介绍
1 public boolean equals (String s) 比较两个字符串内容是否相同、区分大小写
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class StringDemo02 { public static void main (String[] args) { char [] chs = {'a' , 'b' , 'c' }; String s1 = new String (chs); String s2 = new String (chs); String s3 = "abc" ; String s4 = "abc" ; System.out.println(s1 == s2); System.out.println(s1 == s3); System.out.println(s3 == s4); System.out.println("--------" ); System.out.println(s1.equals(s2)); System.out.println(s1.equals(s3)); System.out.println(s3.equals(s4)); } }
用户登录案例 案例需求 已知用户名和密码,请用程序实现模拟用户登录。总共给三次机会,登录之后,给出相应的提示
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class Test1 登录案例 { public static void main (String[] args) { String rightUsername = "itheima" ; String rightPassword = "1234qwer" ; for (int i = 0 ; i < 3 ; i++) { Scanner sc = new Scanner (System.in); System.out.println("请输入用户名" ); String username = sc.next(); System.out.println("请输入密码" ); String password = sc.next(); if (username.equals(rightUsername) && password.equals(rightPassword)) { System.out.println("登录成功" ); break ; } else { if (i == 2 ){ System.out.println("账户" + username + "被锁定,请联系黑马程序员官方小姐姐:XXXXXXX" ); }else { System.out.println("用户名或密码错误,登录失败,还剩下" + (2 - i) + "次机会" ); } } } } }
遍历字符串案例 案例需求 键盘录入一个字符串,使用程序实现在控制台遍历该字符串
直接遍历字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Test2 字符串直接遍历 { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入字符串" ); String str = sc.next(); System.out.println(str); for (int i = 0 ; i < str.length(); i++) { char c = str.charAt(i); System.out.println(c); } } }
统计字符次数案例 案例需求 键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 public class Test4 统计个数 { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入一个字符串" ); String str = sc.next(); int bigCount = 0 ; int smallCount = 0 ; int numberCount = 0 ; for (int i = 0 ; i < str.length(); i++) { char c = str.charAt(i); if (c >= 'a' && c <= 'z' ) { smallCount++; }else if (c >= 'A' && c <= 'Z' ){ bigCount++; }else if (c >= '0' && c <= '9' ){ numberCount++; } } System.out.println("大写字符有:" + bigCount + "个" ); System.out.println("小写字符有:" + smallCount + "个" ); System.out.println("数字字符有:" + numberCount + "个" ); } }
字符串拼接案例 案例需求 定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,调用该方法,
并在控制台输出结果。例如,数组为 int[] arr = {1,2,3}; ,执行方法后的输出结果为:[1, 2, 3]
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 public class Test5 数组拼接成字符串 { public static void main (String[] args) { int [] arr = {1 , 2 , 3 , 4 , 5 }; String str = arrToString(arr); System.out.println(str); } public static String arrToString (int [] arr) { String s = "" ; s = s + "[" ; for (int i = 0 ; i < arr.length; i++) { if (i == arr.length - 1 ){ s = s + arr[i]; }else { s = s + arr[i] + ", " ; } } s = s + "]" ; return s; } public static void printArr (int [] arr) { System.out.print("[" ); for (int i = 0 ; i < arr.length; i++) { if (i == arr.length - 1 ) { System.out.print(arr[i]); } else { System.out.print(arr[i] + ", " ); } } System.out.println("]" ); } }
字符串反转案例 案例需求 定义一个方法,实现字符串反转。键盘录入一个字符串,调用该方法后,在控制台输出结果
例如,键盘录入 abc,输出结果 cba
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class Test6 反转字符串 { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入一个字符串" ); String str = sc.next(); String result = reverse(str); System.out.println(result); } public static String reverse (String str) { String s = "" ; for (int i = str.length() - 1 ; i >= 0 ; i--) { s = s + str.charAt(i); } return s; } }
金额转换 案例需求 把2135变成:零佰零拾零万贰仟壹佰叁拾伍元
把789变成:零佰零拾零万零仟柒佰捌拾玖元
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 package com.itheima.stringdemo;import java.util.Scanner;public class StringDemo9 { public static void main (String[] args) { Scanner sc = new Scanner (System.in); int money; while (true ) { System.out.println("请录入一个金额" ); money = sc.nextInt(); if (money >= 0 && money <= 9999999 ) { break ; } else { System.out.println("金额无效" ); } } String moneyStr = "" ; while (true ) { int ge = money % 10 ; String capitalNumber = getCapitalNumber(ge); moneyStr = capitalNumber + moneyStr; money = money / 10 ; if (money == 0 ) { break ; } } int count = 7 - moneyStr.length(); for (int i = 0 ; i < count; i++) { moneyStr = "零" + moneyStr; } System.out.println(moneyStr); String[] arr = {"佰" ,"拾" ,"万" ,"仟" ,"佰" ,"拾" ,"元" }; String result = "" ; for (int i = 0 ; i < moneyStr.length(); i++) { char c = moneyStr.charAt(i); result = result + c + arr[i]; } System.out.println(result); } public static String getCapitalNumber (int number) { String[] arr = {"零" , "壹" , "贰" , "叁" , "肆" , "伍" , "陆" , "柒" , "捌" , "玖" }; return arr[number]; } }
手机号屏蔽 需求:以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽
最终效果为:131****9468
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Test8 手机号屏蔽 { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入手机号码" ); String phoneNumber = sc.next(); String star = phoneNumber.substring(0 , 3 ); String end = phoneNumber.substring(7 ); String result = star + "****" + end; System.out.println(result); } }
敏感词替换 需求1:键盘录入一个 字符串,如果字符串中包含(TMD),则使用***替换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Test9 敏感词替换 { public static void main (String[] args) { String talk = "后裔你玩什么啊,TMD" ; String result = talk.replace("TMD" , "***" ); System.out.println(talk); System.out.println(result); } }
需求2:如果要替换的敏感词比较多怎么办?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class Test10 多个敏感词替换 { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入要说的话" ); String talk = sc.next(); String[] arr = {"TMD" ,"GDX" ,"ctmd" ,"ZZ" ,"lj" ,"FW" ,"nt" }; for (int i = 0 ; i < arr.length; i++) { talk = talk.replace(arr[i],"***" ); } System.out.println(talk); } }
身份证信息查看 身份证的每一位都是有固定的含义:
1、2位:省份
3、4位:城市
5、6位:区县
7-14位:出生年、月、日
15、16位:所在地派出所
17位:性别(奇数男性,偶数女性)
18位:个人信息码(随机产生)
要求打印内容方式如下:
人物信息为:
出生年月日:XXXX年X月X日
性别为:男/女
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 package com.itheima.stringdemo;public class StringDemo11 { public static void main (String[] args) { String id = "321281202001011234" ; String year = id.substring(6 , 10 ); String month = id.substring(10 , 12 ); String day = id.substring(12 , 14 ); System.out.println("人物信息为:" ); System.out.println("出生年月日:" + year + "年" + month + "月" + day + "日" ); char gender = id.charAt(16 ); int num = gender - 48 ; if (num % 2 == 0 ){ System.out.println("性别为:女" ); }else { System.out.println("性别为:男" ); } } }
StringBuilder StringBuilder 可以看成是一个容器,创建之后里面的内容是可变的。
当我们在拼接字符串和反转字符串的时候会使用到
基本使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class StringBuilderDemo3 { public static void main (String[] args) { StringBuilder sb = new StringBuilder ("abc" ); sb.reverse(); int len = sb.length(); System.out.println(len); System.out.println(sb); } }
链式编程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class StringBuilderDemo4 { public static void main (String[] args) { StringBuilder sb = new StringBuilder (); sb.append("aaa" ).append("bbb" ).append("ccc" ).append("ddd" ); System.out.println(sb); String str = sb.toString(); System.out.println(str); } }
练习1:对称字符串 需求:
键盘接受一个字符串,程序判断出该字符串是否是对称字符串,并在控制台打印是或不是
1 2 3 对称字符串:123321 、111 非对称字符串:123123
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class StringBuilderDemo6 { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入一个字符串" ); String str = sc.next(); String result = new StringBuilder ().append(str).reverse().toString(); if (str.equals(result)){ System.out.println("当前字符串是对称字符串" ); }else { System.out.println("当前字符串不是对称字符串" ); } } }
练习2:拼接字符串 需求:定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回。
调用该方法,并在控制台输出结果。
例如:数组为int[] arr = {1,2,3};
执行方法后的输出结果为:[1, 2, 3]
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.itheima.stringbuilderdemo;public class StringBuilderDemo7 { public static void main (String[] args) { int [] arr = {1 ,2 ,3 }; String str = arrToString(arr); System.out.println(str); } public static String arrToString (int [] arr) { 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("]" ); return sb.toString(); } }
相较于String + ,StringBuilder更快,大概是3s和0.3s的区别
StringJoiner
StringJoiner跟StringBuilder一样,也可以看成是一个容器,创建之后里面的内容是可变的。
作用:提高字符串的操作效率,而且代码编写特别简洁,但是目前市场上很少有人用。
JDK8出现的
基本使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 StringJoiner sj = new StringJoiner ("---" );sj.add("aaa" ).add("bbb" ).add("ccc" ); System.out.println(sj); StringJoiner sj = new StringJoiner (", " ,"[" ,"]" );sj.add("aaa" ).add("bbb" ).add("ccc" ); int len = sj.length();System.out.println(len); System.out.println(sj); String str = sj.toString();System.out.println(str);
关于字符串的小扩展:
字符串存储的内存原理
String s = “abc”;直接赋值
特点:
此时字符串abc是存在字符串常量池中的。
先检查字符串常量池中有没有字符串abc,如果有,不会创建新的,而是直接复用。如果没有abc,才会创建一个新的。
所以,直接赋值的方式,代码简单,而且节约内存。
new出来的字符串
看到new关键字,一定是在堆里面开辟了一个小空间。
String s1 = new String(“abc”);
String s2 = “abc”;
s1记录的是new出来的,在堆里面的地址值。
s2是直接赋值的,所以记录的是字符串常量池中的地址值。
==号比较的到底是什么?
如果比较的是基本数据类型:比的是具体的数值是否相等。
如果比较的是引用数据类型:比的是地址值是否相等。
结论:==只能用于比较基本数据类型。不能比较引用数据类型。
包装类&装箱拆箱 基本类型包装类 基本类型包装类的作用
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
常用的操作之一:用于基本数据类型与字符串之间的转换
基本类型对应的包装类
基本数据类型
包装类
byte
Byte
short
Short
int
Integer
long
Long
float
Float
double
Double
char
Character
boolean
Boolean
Integer类 包装一个对象中的原始类型 int 的值
方法名
说明
public Integer(int value)
根据 int 值创建 Integer 对象**(过时)**
public Integer(String s)
根据 String 值创建 Integer 对象**(过时)**
public static Integer valueOf(int i)
返回表示指定的 int 值的 Integer 实例
public static Integer valueOf(String s)
返回一个保存指定值的 Integer 对象 String
自动拆箱和自动装箱 自动装箱
自动拆箱
自动拆装箱是JDK1.5新特性,可以实现基本数据类型与对应的包装类之间无缝使用!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class IntergerDemo3 { public static void main (String[] args) { Integer i1 = 100 ; System.out.println("自动装箱i1为interger:" +i1); int i2 = i1; System.out.println("自动拆箱i2为int:" +i2); Integer i3 = 100 ; i3 += 200 ; System.out.println("自动拆装箱,最后i3为Interger类型:" +i3); Integer i4 = null ; if (i4 != null ) { i4 += 200 ; System.out.println(i4); } } }
int类型如何转为String类型
第一种方式:直接在int类型数据后面加
一个空字符串
第二种方式:通过String的静态方法valueOf()
String类型如何转为int类型
第一种方式:先将String转为Integer类型,再通过valueOf()方法转为int
第二种方式:通过Integer静态方法parseInt()
Math 1、Math类概述
Math 包含执行基本数字运算的方法
2、Math中方法的调用方式
Math类中无构造方法,但内部的方法都是静态的,则可以通过 类名.进行调用
3、Math类的常用方法
1 2 3 4 5 6 7 8 public static int abs (int a) 返回参数的绝对值public static double ceil (double a) 返回大于或等于参数的最小double 值,等于一个整数public static double floor (double a) 返回小于或等于参数的最大double 值,等于一个整数public static int round (float a) 按照四舍五入返回最接近参数的int public static int max (int a,int b) 返回两个int 值中的较大值public static int min (int a,int b) 返回两个int 值中的较小值public static double pow (double a,double b) 返回a的b次幂的值public static double random () 返回值为double 的正值,[0.0 ,1.0 )
4、举例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package Nomal_API.APIdemo;public class MathDemo { public static void main (String[] args) { int abs = Math.abs(10 ); System.out.println("abs的绝对值为:" +abs); double ceil = Math.ceil(10.1 ); System.out.println("ceil的向上取整:" +ceil); double floor = Math.floor(10.9 ); System.out.println("floor的向下取整为:" +floor); long round = Math.round(10.1 ); System.out.println("round的四舍五入为:" +round); long round1 = Math.round(1.9 ); System.out.println("round1的四舍五入为:" +round1); int max = Math.max(10 , 20 ); System.out.println("max的最大值为:" +max); int min = Math.min(10 , 20 ); System.out.println("min的最小值为:" +min); double pow = Math.pow(2 , 3 ); System.out.println("pow的幂次方为:" +pow); System.out.println("随机值【double类型】" ); for (int i = 0 ; i < 10 ; i++) { double random = Math.random(); System.out.println(random); } } }
System 1、方法
1 2 public static void exit (int status) 终止当前运行的 Java 虚拟机,非零表示异常终止public static long currentTimeMillis () 返回当前时间(以毫秒为单位)
2、例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Systemdemo { public static void main (String[] args) { long start = System.currentTimeMillis(); System.out.println("开始时间为" +start); int i; for (i = 1 ; i <= 10000 ; i++) { int c = 0 ; c += i; } long end = System.currentTimeMillis(); System.out.println("结束时间为:" +end); System.out.println("循环" +i+"共耗时:" + (end - start) + "毫秒" ); } }
Object 概述 java.lang.Object类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。
如果一个类没有特别指定父类, 那么默认则继承自Object类。例如:
1 2 3 public class MyClass { }
根据JDK源代码及Object类的API文档,Object类当中包含的方法有11个。今天我们主要学习其中的2个:
public String toString():返回该对象的字符串表示。
public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。
toString方法 方法摘要
由于toString方法返回的结果是内存地址,而在开发中,经常需要按照对象的属性得到相应的字符串表现形式,因此也需要重写它
覆盖重写 如果不希望使用toString方法的默认行为,则可以对它进行覆盖重写。例如自定义的Person类:
1 2 3 4 5 6 7 8 9 10 11 12 public class Person { private String name; private int age; @Override public String toString () { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}' ; } }
在IntelliJ IDEA中,可以点击Code菜单中的Generate…,也可以使用快捷键alt+insert,点击toString()选项。选择需要包含的成员变量并确定。如下图所示:
equals方法 方法摘要
public boolean equals(Object obj):指示其他某个对象是否与此对象“相等”。
调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。
默认地址比较 如果没有覆盖重写equals方法,那么Object类中默认进行==运算符的对象地址比较,只要不是同一个对象,结果必然为false。
对象内容比较 如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。例如:
1 2 3 4 5 6 7 8 9 10 11 12 public class Person { private String name; private int age; @Override public String toString () { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}' ; } }
这段代码充分考虑了对象为空、类型一致等问题,但方法内容并不唯一。大多数IDE都可以自动生成equals方法的代码内容。在IntelliJ IDEA中,可以使用Code菜单中的Generate…选项,也可以使用快捷键alt+insert,并选择equals() and hashCode()进行自动代码生成。
Objects 1、方法
1 2 3 4 public static String toString (对象) 返回参数中对象的字符串表示形式。public static String toString (对象, 默认字符串) 返回对象的字符串表示形式。public static Boolean isNull (对象) 判断对象是否为空public static Boolean nonNull (对象) 判断对象是否不为空
2、例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 class Student { private String name; private int age; public Student () { } public Student (String name, int age) { this .name = name; this .age = age; } 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; } @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}' ; } } import java.util.Objects;public class MyObjectsDemo { public static void main (String[] args) { Student s1 = new Student ("小小同学" ,50 ); String result1 = Objects.toString(s1); System.out.println(result1); System.out.println(s1); Student s2 = new Student ("小花同学" ,23 ); Student s3 = null ; String result2 = Objects.toString(s3, "随便写一个" ); System.out.println(result2); Student s4 = null ; Student s5 = new Student (); boolean result3 = Objects.isNull(s5); System.out.println("对象是否为空:" +result3); Student s6 = new Student (); Student s7 = null ; boolean result4 = Objects.nonNull(s6); System.out.println("对象是否不为空" + result4); } }
BigDecimal 1、作用
可以用来进行精确计算
2、构造方法
1 2 BigDecimal(double val) 参数为double BigDecimal (String val) 参数为String
3、常用方法
1 2 3 4 5 6 7 8 9 public BigDecimal add (另一个BigDecimal对象) 加法public BigDecimal subtract (另一个BigDecimal对象) 减法public BigDecimal multiply (另一个BigDecimal对象) 乘法public BigDecimal divide (另一个BigDecimal对象) 除法public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) 除法舍入模式: BigDecimal.ROUND_UP 进一法 BigDecimal.ROUND_FLOOR 去尾法 BigDecimal.ROUND_HALF_UP 四舍五入
4、例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package Nomal_API.APIdemo.bigdecimal;import java.math.BigDecimal;public class BigdecimalDemo { public static void main (String[] args) { BigDecimal bd1 = new BigDecimal ("10.0" ); BigDecimal bd2 = new BigDecimal ("0.4" ); System.out.println("字符串数字" +bd1); System.out.println(bd2); BigDecimal bd3 = new BigDecimal ("0.1" ); BigDecimal bd4 = new BigDecimal ("0.2" ); BigDecimal add = bd3.add(bd4); System.out.println("和为" + add); BigDecimal subtract = bd3.subtract(bd4); System.out.println("差为" + subtract); BigDecimal multiply = bd1.multiply(bd2); System.out.println("积为" + multiply); BigDecimal divide = bd1.divide(bd2); System.out.println("商为" + divide); } } import java.math.BigDecimal;public class MyBigDecimalDemo4 { public static void main (String[] args) { BigDecimal bd1 = new BigDecimal ("0.3" ); BigDecimal bd2 = new BigDecimal ("4" ); BigDecimal divide = bd1.divide(bd2, 2 , BigDecimal.ROUND_HALF_UP); System.out.println(divide); } }
时间日期类 Date类 java.util.Date
代表了一个特定的时间,精确到毫秒
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.DateTest1;import java.util.Date;public class DateDemo1 { public static void main (String[] args) { Date d1 = new Date (); System.out.println(d1); long date = 1000 * 60 * 60 ; Date d2 = new Date (date); System.out.println(d2); } }
tips: 由于我们处于东八区,所以我们的基准时间为1970年1月1日8时0分0秒。
Date类常用方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.DateTest1;import java.util.Date;public class DateDemo2 { public static void main (String[] args) { Date d = new Date (); System.out.println(d.getTime()); System.out.println(d.getTime() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年" ); System.out.println("----------------------" ); long time = 1000 * 60 * 60 ; d.setTime(time); System.out.println(d); } }
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期
常用方法
格式化(从Date到String):public final String format(Date date): 将日期格式化成日期/时间字符串
解析(从String到Date):public Date parse(String source): 从给定字符串的开始解析文本以生成日期
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package com.SimpleDateFormatTest1;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;public class SimpleDateFormatDemo { public static void main (String[] args) throws ParseException { Date d = new Date (); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy年MM月dd日 HH:mm:ss" ); String s = sdf.format(d); System.out.println(s); System.out.println("---------" ); String ss = "2048-08-09 11:11:11" ; SimpleDateFormat sdf2 = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss" ); Date dd = sdf2.parse(ss); System.out.println(dd); } }
日期工具类案例 需求:定义一个日期工具类(DateUtils),包含两个方法:把日期转换为指定格式的字符串;把字符串解析成指定格式的日期,然后定义一个测试类(DateDemo),测试日期工具类的方法
工具类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.DateSDFTest2;import java.text.ParseException;import java.util.Date;public class DateSDFDemo { public static void main (String[] args) throws ParseException { Date d = new Date (); String s1 = DateUtils.dateToString(d, "yyyy年MM月dd日 HH:mm:ss" ); System.out.println(s1); String s2 = DateUtils.dateToString(d, "yyyy年MM月dd日" ); System.out.println(s2); String s3 = DateUtils.dateToString(d, "HH:mm:ss" ); System.out.println(s3); System.out.println("--------" ); String s = "2048-08-08 12:12:12" ; Date dd = DateUtils.stringToDate(s, "yyyy-MM-dd HH:mm:ss" ); System.out.println(dd); } }
Calender类 Calendar为特定瞬间与一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法
Calendar提供了一个类方法getinstance用于获取这种类型的一般有用的对象
该方法返回一个Calendar对象
其日历字段已使用当前日期和时间初始化:Calendar rightNow = Calendar.getInstance();
常用方法
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.CalendarTest;import java.util.Calendar;public class CalendarDemo { public static void main (String[] args) { Calendar c = Calendar.getInstance(); int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH) + 1 ; int date = c.get(Calendar.DATE); System.out.println(year + "年" + month + "月" + date + "日" ); c.add(Calendar.YEAR, -3 ); year = c.get(Calendar.YEAR); month = c.get(Calendar.MONTH) + 1 ; date = c.get(Calendar.DATE); System.out.println(year + "年" + month + "月" + date + "日" ); c.add(Calendar.YEAR, 10 ); c.add(Calendar.DATE, -10 ); year = c.get(Calendar.YEAR); month = c.get(Calendar.MONTH) + 1 ; date = c.get(Calendar.DATE); System.out.println(year + "年" + month + "月" + date + "日" ); c.set(2050 , 10 , 10 ); year = c.get(Calendar.YEAR); month = c.get(Calendar.MONTH) + 1 ; date = c.get(Calendar.DATE); System.out.println(year + "年" + month + "月" + date + "日" ); } }
二月天案例
需求:获取任意一年的二月有多少天
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.CalendarTest;import java.util.Calendar;import java.util.Scanner;public class CalendarTest { public static void main (String[] args) { Scanner sc = new Scanner (System.in); System.out.println("请输入年:" ); int year = sc.nextInt(); Calendar c = Calendar.getInstance(); c.set(year, 2 , 1 ); c.add(Calendar.DATE, -1 ); int date = c.get(Calendar.DATE); System.out.println(year + "年的2月分有" + date + "天" ); } }
JDK8以后
LocalDateTime JDK8及之后的新日期时间API JDK 1.0 中包含了一个 java.util.Date 类,但是它的大多数方法已经在 JDK 1.1 引入 Calendar 类之后被弃用了。而 Calendar 并不比 Date 好多少。他们面临的问题是:
可变性:像日期和时间这样的类应该是不可变的
偏移性:Date 中的年份是从 1900 开始的,而月份都从 0 开始
格式化:格式化只对 Date 有用,Calendar 则不行
此外,它们的线程也不是安全的
1 2 3 4 5 6 7 8 9 10 11 import org.junit.Test;import java.util.Date; public class MyTest { @Test public void test () { Date date = new Date (2022 - 1900 ,3 - 1 ,20 ); System.out.println(date); } }
因此为了更高效的获取时间信息,JDK 8 及之后设置了新的日期时间 API:java . time
java.time.LocalDate/LocalTime/LocalDateTime LocalDateTime 相较于 LocalDate 和 LocalTime ,使用频率更高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import org.junit.Test;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime; public class MyTest { @Test public void test () { LocalDate ld = LocalDate.now(); LocalTime lt = LocalTime.now(); LocalDateTime ldt = LocalDateTime.now(); System.out.println(ld); System.out.println(lt); System.out.println(ldt); LocalDateTime ldt1 = LocalDateTime.of(2022 ,3 ,20 ,6 ,45 ); System.out.println(ldt1); System.out.println(ld.getDayOfWeek()); LocalDate ld1 = ld.withDayOfMonth(22 ); System.out.println(ld); System.out.println(ld1); } }
Instant java.time.Instant
Instant 时间线上的瞬时点。这可能被用来记录应用程序中的事件时间戳
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import org.junit.Test;import java.time.Instant;import java.time.OffsetDateTime;import java.time.ZoneOffset; public class MyTest { @Test public void test () { Instant instant = Instant.now(); System.out.println(instant); OffsetDateTime odf = instant.atOffset(ZoneOffset.ofHours(8 )); System.out.println(odf); long milli = instant.toEpochMilli(); System.out.println(milli); Instant instant1 = Instant.ofEpochMilli(1648977151854L ); System.out.println(instant1); } }
java.time.format.DateTimeFormatter
可以格式化和解析日期与时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import org.junit.Test;import java.time.LocalDateTime;import java.time.format.DateTimeFormatter;import java.time.format.FormatStyle;import java.time.temporal.TemporalAccessor; public class MyTest { @Test public void test () { DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; LocalDateTime localDateTime = LocalDateTime.now(); String str1 = formatter.format(localDateTime); System.out.println(str1); TemporalAccessor parse = formatter.parse("2022-04-03T17:21:33.470" ); System.out.println(parse); DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG); String str2 = formatter1.format(localDateTime); System.out.println(str2); DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss" ); String str3 = formatter2.format(LocalDateTime.now()); System.out.println(str3); } }
递归 递归的概述 递归的概述
生活中的递归: 放羊–赚钱–盖房子–娶媳妇–生娃–放羊–赚钱–盖房子–娶媳妇–生娃–放羊…
程序中的递归: 指在当前方法内调用自己的这种现象。
递归的注意事项:
递归要有出口(结束方法),否则会报栈内存溢出错误StackOverflowError
递归的出口不能太晚了
案例演示 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Test { static int count = 0 ; public static void main (String[] args) { method(); } public static void method () { count++; if (count == 70000 ){ return ; } System.out.println("method 方法执行了..." ); method(); } }
递归累和 需求
分析
num的累加和 = num + (num-1)的累和,所以可以把累加和的操作定义成一个方法,递归调用。
实现 代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class Test1 { public static void main (String[] args) { int sum = getSum(5 ); System.out.println("5的累加和:" +sum); } public static int getSum (int n) { if (n == 1 ){ return 1 ; } return n + getSum(n-1 ); } }
代码执行图解
递归求阶乘 需求
分析
1 n的阶乘:n! = n * (n-1 ) *...* 3 * 2 * 1
n的阶乘 = n * (n1)的阶乘,所以可以把阶乘的操作定义成一个方法,递归调用。
实现 代码实现 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class Test2 { public static void main (String[] args) { int res = jieCheng(5 ); System.out.println("5的阶乘:" +res); } public static int jieCheng (int num) { if (num == 1 ){ return 1 ; } return num * jieCheng(num-1 ); } }
Arrays操作数组 为什么用Arrays 之前学了哪些复制,反转,二分查找,排序等,实际上是要你记住实现的思想,实际开发中我们使用Arrays工具类操作数组。
怎么用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class $_03_ 工具类Arrays { public static void main (String[] args) { int [] arr1 = new int []{1 ,2 ,3 ,4 }; int [] arr2 = new int []{1 ,3 ,2 ,4 }; boolean isEquals = Arrays.equals(arr1, arr2); System.out.println("isEquals = " + isEquals); String str = Arrays.toString(arr1); System.out.println("str = " + str); Arrays.fill(arr1,10 ); System.out.println(Arrays.toString(arr1)); Arrays.sort(arr2); System.out.println(Arrays.toString(arr2)); int [] arr = new int []{-99 , -54 , -2 , 0 , 2 , 33 , 43 , 256 , 999 }; int index = Arrays.binarySearch(arr, 210 ); System.out.println("index = " + index); } }
枚举 1.简介 1.一个类的实例是有限且固定的,这个类称为枚举类。比如季节类,只有四个对象(春、夏、秋、冬)
2.手动实现一个枚举类 (1)通过private将构造器隐藏起来 (2)把这个类的所有可能实例都使用private static final修饰的类变量来保存。 (3)如果有必要,可以提供一些静态方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package cn.it.lsl;public class Season { private final String name; private final String desc; private Season (String name, String desc) { this .name = name; this .desc = desc; } public static final Season SPRING = new Season ("春天" ,"踏青" ); public static final Season SUMMER = new Season ("夏天" ,"夏日炎炎" ); public static final Season FAIL = new Season ("秋天" ,"秋高气爽" ); public static final Season WINTER = new Season ("冬天" ,"白雪皑皑" ); public String getName () { return this .name; } public String getDesc () { return this .desc; } }
1 2 3 4 5 6 7 8 9 10 package cn.it.lsl;public class SeasonTest { public SeasonTest (Season s) { System.out.println(s.getName() + "," + s.getDesc()); } public static void main (String[] args) { new SeasonTest (Season.FAIL); } }
Season类是一个不可变类。Season类中包含了4个static final常量的Field,这4个常量Field就代表了该类所能创建的对象。当程序需要调用Season对象时,就可以通过Season.SPRING的方式来取得Season对象。
这里顺便复习一下不可变类 不可变类:创建该类的实例后,该实例的Field是不可改变的。 如果要创建自定义的不可变类,需遵循如下规则: (1)使用private和final修饰符来修饰该类的Field。 (2)提供带参数的构造函数,用于根据传入参数来初始化类里的Field。 (3)仅为该类的Field提供getter方法,不要为该类的Field提供setter方法。 (4)如果有必要,重写Object类的hashCode和equals方法。
3.枚举类 (1)使用enum关键字定义枚举类。枚举类一样可以有自己的Field、方法,可以实现一个或多个接口,也可以有自己的构造器。 (2)使用eunm定义的枚举类默认继承了java.lang.Enum类,而不是继承Object类。 (3)使用enum定义、非抽象的枚举类默认会使用final修饰,因此枚举类不能派送子类。(并不是所有的枚举类都使用final修饰,如抽象枚举类) (4)枚举类所有实例必须在枚举类的第一行显示列出,否则这个枚举类永远不能产生实例。 (5)所有枚举类都提供一个values方法,该方法可以方便地遍历所有枚举值。
1 2 3 4 5 package cn.lsl;public enum SeasonEnum { SPRING,SUMMER,FALL,WINTER; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package cn.lsl;public class EnumTest { public void judge (SeasonEnum s) { switch (s){ case SPRING: System.out.println("春天" ); break ; case SUMMER: System.out.println("夏天" ); break ; case FALL: System.out.println("秋天" ); break ; case WINTER: System.out.println("冬天" ); break ; } } public static void main (String[] args) { for (SeasonEnum s : SeasonEnum.values()){ System.out.println(s); } new EnumTest ().judge(SeasonEnum.FALL); } }
4.枚举类的Field、方法 枚举类可以定义自己的Field和方法。
1 2 3 4 5 6 package cn.lsl;public enum Gender { MALE,FEMALE; public String name; }
1 2 3 4 5 6 7 8 9 10 package cn.lsl;public class GenderTest { public static void main (String[] args) { Gender g = Enum.valueOf(Gender.class, "FEMALE" ); g.name = "女" ; System.out.println(g + "," + g.name); } }
在上面程序中产生Gender对象的方式与普通类不同,而是采用通过Enum的valueOf方法来获取指定枚举类的枚举值,枚举类的实例只能是枚举值,而不是随意通过new来创建的。
其实上面程序中,没有实现java的良好封装,因为name的访问权限是public,这样就会出现随意对name赋值的情况,应该通过方法来控制对name的访问。
改造上面的程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package cn.lsl;public enum Gender { MALE,FEMALE; public String name; public void setName (String name) { switch (this ){ case MALE: if (name.equals("男" )){ this .name = name; }else { System.out.println("参数错误" ); return ; } break ; case FEMALE: if (name.equals("女" )){ this .name = name; }else { System.out.println("参数错误" ); return ; } break ; } } public String getName () { return this .name; } }
1 2 3 4 5 6 7 8 9 10 11 12 package cn.lsl;public class GenderTest { public static void main (String[] args) { Gender g = Enum.valueOf(Gender.class, "FEMALE" ); g.setName("女" ); System.out.println(g + "," + g.getName()); g.setName("男" ); System.out.println(g + "," + g.getName()); } }
定义枚举类,以上的做法还是做的不够好,枚举类通常应该设计不可变类。其Field值不应该允许改变,这样会更安全。
所以枚举类的Field都应该使用private final修饰。
1 2 3 4 5 6 7 8 9 10 11 12 package cn.lsl;public enum Gender { MALE("男" ),FEMALE("女" ); private final String name; private Gender (String name) { this .name = name; } public String getName () { return this .name; } }
5.实现接口的枚举类 枚举类可以实现一个或多个接口。
1 2 3 4 5 package cn.it.lsl;public interface GenderDesc { void info () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package cn.it.lsl;public enum Gender implements GenderDesc { MALE("男" ),FEMALE("女" ); private final String name; private Gender (String name) { this .name = name; } public String getName () { return this .name; } @Override public void info () { System.out.println("枚举类实现接口" ); } }
以上在枚举类里面实现接口的方法时,每个枚举值在调用该方法的时候都会有相同的行为(即方法体相同)。 如果需要每个枚举值在调用该方法时表现出不同的行为方式,应该让每个枚举值分别实现该方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package cn.it.lsl;public enum Gender implements GenderDesc { MALE("男" ){ public void info () { System.out.println("枚举类实现接口,男" ); } }, FEMALE("女" ){ public void info () { System.out.println("枚举类实现接口,女" ); } }; private final String name; private Gender (String name) { this .name = name; } public String getName () { return this .name; } }
6.包含抽象方法的枚举类 在枚举类中定义抽象方法的时候不能使用abstract关键字将枚举类定义成抽象类(因为系统会自动为它添加abstract关键字),因为枚举类需要显示创建枚举值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现。
以下一个程序在枚举类中定义了一个抽象方法,这个抽象方法由不同的枚举值提供不同的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package cn.it.lsl;public enum Operation { PLUS{ @Override public double eval (double x, double y) { return x + y; } }, MINUS{ @Override public double eval (double x, double y) { return x - y; } }, TIMES{ @Override public double eval (double x, double y) { return x * y; } }, DIVIDE{ @Override public double eval (double x, double y) { return x / y; } }; public abstract double eval (double x, double y) ; public static void main (String[] args) { System.out.println(Operation.PLUS.eval(2 , 3 )); System.out.println(Operation.MINUS.eval(2 , 3 )); System.out.println(Operation.TIMES.eval(2 , 3 )); System.out.println(Operation.DIVIDE.eval(2 , 3 )); } }