JAVA实战小项目——输入验证码
生活中有很多需要登陆账户的情况,在输入账号密码以后还需要输入验证码,本文将实现一个输入一个四位验证码的小项目。
验证码是仅由0-9数字和所有字母构成,并且生成的验证码完全是随机的。那么先拿一个字符串保存所有的数字和字母,然后由这个字符串随机生成。
那么就可以在这个字符串的长度范围内,随机生成一个下标,再根据这个下标取出字符串中的那个字符,如此再生成第二个数字或字母,直到第四个。这样就生成了随机的四位验证码。
import java.util.Random;
import java.util.Scanner;public class Test2 {public static void main(String[] args) {char[] VerCode=new char[4];Random rand=new Random();String RandomStr="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";for(int i=0;i<VerCode.length;i++){int randIndex=rand.nextInt(RandomStr.length());VerCode[i]=RandomStr.charAt(randIndex);}}
}
我们都知道,验证码的验证是不区分大小写的,所以可以在用户输入前先转换成小写,然后用户输入后,也都转换成小写再进行比较是否相等。不过转换成小写先要将这个字符数组转为string类型,因为string类里面是封装了转小写的功能。
但是当tostring转为string类了以后,它确实可以转小写,可是打印出来看的时候又不对了
这时候它显示的不再是它的内容了,而是它的地址,那为什么会这样呢?
数组作为一种引用类型,自然也继承了object类,而在object中的tostring就是转为一串地址,数组类中也没有去重写这个方法,固然使用的还是object中的tostring方法。同样里面的equals也没有重写,所以在后续进行比较时也将会比较地址,这种比较方式肯定不是我们想要的,想要比较内容就必须重写方法。
既然tostring还要重写那干脆就不要tostring了,直接用这个字符数组来初始化一个新建string类型的code,然后再和输入进行比较
String code=new String(VerCode);System.out.println(code);System.out.println("请输入验证码:");Scanner sc=new Scanner(System.in);String input=sc.nextLine();
在string类里面已经封装了一个忽略大小写的比较方法equalsIgnoreCase,直接用起来就很方便,不过有个细节需要注意,应该要让code去调用这个比较方法而不能用input,因为有的用户可能很坏,直接输入一个空的。
if(code.equalsIgnoreCase(input))System.out.println("输入正确");elseSystem.out.println("验证码错误");
不管输入正确与否,程序都会结束,需要重新获取验证码,这也合乎常理,毕竟实际运用中只要输入错误,那么这个验证码就失效了,需要重新生成验证码。
最后代码和运行结果如下:
import java.util.Scanner;
import java.util.Random;
import java.util.Arrays;public class Test {public static void main(String[] args) {char[] VerCode=new char[4];Random rand=new Random();String RandomStr="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";for(int i=0;i<VerCode.length;i++){int randIndex=rand.nextInt(RandomStr.length());VerCode[i]=RandomStr.charAt(randIndex);}String code=new String(VerCode);System.out.println(code);System.out.println("请输入验证码:");Scanner sc=new Scanner(System.in);String input=sc.nextLine();if(code.equalsIgnoreCase(input))System.out.println("输入正确");elseSystem.out.println("验证码错误");}
}
那如果非要去重写string类里面的方法呢,想按照那就要自己去造一个类,里面有一个字符型数组,然后在里面重写tostring方法,要进行比较还要重写equals和hashcode。equals和hashcode可以自动生成:右键点击生成,然后选择equals和hashcode,即可自动生成。
而tostring需要让它输出内容而非地址,在tostring中就应该自己用arr字符数组来给字符串s赋值。
public String toString() {String s = new String(arr);return s;}
顺便这个类里面我们还可以做一件事,将所有的大写字母转小写,这样方便后续的比较。就可以提供一个LowerArr的方法:
public LowerArr(char[] arr){this.arr=new char[arr.length];for(int i=0;i<arr.length;i++){if(arr[i]>='A'&&arr[i]<='Z'){this.arr[i]=(char)(arr[i]+32);}else{this.arr[i]=arr[i];}}}
那么整个类就实现或重写了如下功能:
import java.util.Arrays;
import java.util.Objects;public class LowerArr {private final char[] arr;public LowerArr(char[] arr){this.arr=new char[arr.length];for(int i=0;i<arr.length;i++){if(arr[i]>='A'&&arr[i]<='Z'){this.arr[i]=(char)(arr[i]+32);}else{this.arr[i]=arr[i];}}}@Overridepublic String toString() {String s = new String(arr);return s;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;LowerArr lowerArr = (LowerArr) o;return Objects.deepEquals(arr, lowerArr.arr);}@Overridepublic int hashCode() {return Arrays.hashCode(arr);}
}
在主函数中就可以创建这个类而不是string类,只有自己写的这个类里面的tostring和比较equals才能达到想要的功能
主函数代码如下:
import java.util.Random;
import java.util.Scanner;public class Test {public static void main(String[] args) {char[] VerCode=new char[4];Random rand=new Random();String RandomStr="0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";for(int i=0;i<VerCode.length;i++){int randIndex=rand.nextInt(RandomStr.length());VerCode[i]=RandomStr.charAt(randIndex);}LowerArr lowercode=new LowerArr(VerCode);System.out.println(lowercode);Scanner sc=new Scanner(System.in);String input=sc.nextLine();char[] inputChar=input.toCharArray();LowerArr inputLower=new LowerArr(inputChar);System.out.println(inputLower);if(lowercode.equals(inputLower))System.out.println("输入正确");elseSystem.out.println("验证码错误");}
}
如此一来,用自己类重写的tostring和equals的方式代码量比较大,而且我们仅仅是因为需要重写这两个方法就单独又造了一个类,这就让程序的侵入性变大。
侵入性是软件设计中需要重点考虑的因素,合理的低侵入性设计可以显著提高软件的可维护性、可扩展性和稳定性。