密码输入
控制台输入命令为了安全不适用Scanner类,而是使用Console类。
Console console=System.console();
String usernamr=console.readLine("username:");
char[] password=console.readPassword("password:");
需要注意的是:该方法只能在控制台使用,密码使用字符串数组接受,使用完成后即使将其覆盖掉。
printf格式化打印日期
Date date=new Date();
System.out.printf("%tc\n",date); // 完整的时间日期
System.out.printf("%tF\n",date); // 日期
System.out.printf("%tT",date); // 24小时时间
格式化参数有两个字母,第一个总是t,后面的一个参数类型很多,这里没有介绍。
大数
java.math包下的BigInteger和BigDecimal用来满足基本的整数和浮点型不能满足需求的情况。
BigInteger a=BigInteger.valueOf(100);
BigInteger b=new BigInteger("1000000000000000000000000000000000");
System.out.println(a.add(b));
System.out.println(b.subtract(a));
System.out.println(b.multiply(a));
System.out.println(b.divide(a));
System.out.println(b.mod(a));
System.out.println(b.compareTo(a));
需要注意,大数的计数不能直接使用+,-,*,/等运算符,而是要使用它提供的计算函数,因为Java不支持运算符的重载。
数组的拷贝
int[] array1=new int[]{1,2,3,4};
// 浅拷贝,相当于引用
int[] array2=array1;
// 深拷贝
int[] array3= Arrays.copyOf(array1,array1.length); // 长度不一定要相等
Java 可变参数
Java使用…表示接受任意数量的参数。
add(int... values)
max(double... values)
find(object... objs)
枚举类型
Java通过enum关键字声明一组枚举常量,其构造器必须是私有的。其常用的几个方法有
public enum Size={SMALL, MEDIUM, LARGE}
- toString()
该方法返回枚举常量名,其逆方法是Enum.ValueOf()方法,是一个静态方法。
System.out.println(Size.SAMLL.toString());
Size s=Enum.valueOf(Size.class,"SMALL");
- values() ,该方法返回一个包含全部枚举值的数组
Size[] values=Size.values();
- ordinal() 返回枚举常量的位置
Size.SMALL.ordinal()
Number 类型
Number是Java.lang包下的一抽象类,是所有的包装类的父类,是abstract类型的,不可实例化。
Date类
Date类提供了两个函数,
Date date=new Date();
Date date1=new Date(0,8,3);
需要注意的是,第二种构造方式的年份是从1900往上加的,比如2021年应该是1900+121,所以是new Date(121,8,3).第一种方式构造的是当前的时间日期。Date提供许多的日之间的比较方法
可以利用SimpleDateFormat来规范日期的格式,比如
SimpleDateFormat df=new SimpleDateFormat("E yy.mm.dd HH:MM:SS");
时间模式字符串用来指定时间格式,在该模式中,所有的时间格式被保留为模式字母,大多数都比较好记,比如year:y, month:m, day:d, hour:H, Minutes:m, seconds:s ,具体如下
Java正则表达式
Java正则表达式主要包括3个类,Pattern,Matcher类,PatternSyntaxException类。其语法主要有
Matcher类的方法
1、索引方法
2、研究方法
检查是否包某个字符串,返回boolean值
3、替换方法
java 文件、流、IO
java流分为两类,字节流和字符流,主要区别如下:
字节流 | 字符流 |
---|---|
处理的最小单位字节 | 处理的最小单位字符两个字节) |
不需要缓冲区 | 需要使用缓冲区,写完后需要手动刷到文件 |
可以处理任何类型 | 一般处理文本文件 |
从上图中,根据后缀就可以很轻易的看出一个类是处理字节流还是处理字符流。
文件
使用File创建一个File对象来对文件进行操作
mkdir 创建一个文件夹,
mkdirs创建一个文件夹和它的父文件夹。
String dirname = "/tmp/user/java/bin";
File d = new File(dirname);
// 现在创建目录
d.mkdirs();
比较常用的方法有
方法 | 含义 |
---|---|
isDirectory | 判断是否是一个文件夹 |
lists | 返回包含文件和文件夹的列表 |
delete | 删除一个文件或者一个文件夹,如果是文件夹,需要确保它下面没有其他的文件,如果有可以使用递归删除的方式 |
序列化
对象序列化后可以方便在网络上进行传输,方便存储。
Serializable
一个类通过实现java.io.Serializable便可以序列化到文件中,一个类能够被序列化的前提是
1、实现java.io.Serializable接口
2、所有属性都是可以序列化的,如果有属性不需要序列化,那么给它标记上transcient.
如果序列化失败,可能需要为其添加上UID,idea中可以设置为自动添加,UID是用来验证版本一致性的,是能否序列化成功的关键,一般情况最好都加上。
该方法的比较简单,只需要实现java.io.Serializable接口就行了,其它工作不需要我们去做。
ObjectOutputStream outputStream=new ObjectOutputStream(new FileOutputStream("employee.ser"));
Employee employee=new Employee("xudong",21);
outputStream.writeObject(employee);
outputStream.close();
反序列化时也简单
ObjectInputStream inputStream=new ObjectInputStream(new FileInputStream("employee.ser"));
Employee employee1= (Employee) inputStream.readObject();
在进行反序列化操作时,一般会创造一个新的对象,这就可能会破坏单例模式,反序列化操作提供了一个很特别的钩子函数,类中有一个私有的readResolve()函数,这个函数可以让我们控制对象的反序列化,如果不想让它生成新的对象,必须加入这个函数。
class Singleton implements Serializable{
private Singleton(){
}
private static final Singleton SINGLETON=new Singleton();
public static Singleton getInstance(){
return SINGLETON;
}
private Object readResolve() throws ObjectStreamException{
return SINGLETON;
}
}
Parceable
parceable比较复杂,但效率却比Serializabl效率高得多,是Google官方推荐的方式。
一个类也要实现Parcelable接口才能序列化。例如类Book
class Book implements Pracelable{
public String name;
public float price;
public int pages;
}
1、实现它的两个抽象方法
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
}
其中describeContents()直接返回0就可以了,而writeToParcel需要调用Parcel中的writexxx()方法将各个属性写出,比如
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeFloat(price);
dest.writeInt(pages);
}
最后,还必须为其提供一个名为CREATOR的匿名类实现,创建一个Parceable.creator接口的一个实现,并指定泛型为Book。
public static final Creator<Book> CREATOR = new Creator<Book>() {
@Override
public Book createFromParcel(Parcel in) {
String name = in.readString();
float price = in.readFloat();
int pages = in.readInt();
return new Book(name,price,pages);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
在 createFromParcel()方法中需要按照写入的顺序读出各个属性值,然后返回一个Book对象,newArray方法不需要修改。当然,如果记不住这些的话,也可以不修改这两个方法,直接在protected Book(Pacel in)方法中读取出各个属性的值也可,因为createFromPacel方法就是调用这个构造函数构造一个对象进行返回的。
protected Book(Parcel in) {
name = in.readString();
price = in.readInt();
pages = in.readInt();
}
JSON
JSON是一种键值对类型的数据格式,有效的数据类型有
- 字符串
{"name":"zhangsan"}
- 数字,int或者float类型
{"age":23}
- 对象
{"employee":{"name","zhangsan"}}
- 数组
{"employee":["zhangsan","wanger"]}
- 布尔类型
{"safe":true}
- null
不支持的类型
- 函数
- 日期
- undefined
protected关键字
-
同一个包下,任何地方都可以访问protected修饰的成员和方法
-
不同包下,分为直接子类和间接子类两种情况,比如
package package2; public class People { protected String name; public People(String name) { this.name = name; } protected String Introduce(){ return name; } } // package package1; public class Worker extends People { public Worker(String name) { super(name); } } class Wife extends Worker{ public Wife(String name) { super(name); } }
上面这种情况,如果我们实例化一个Worker和一个Wife对象,分别为worker和wife,那么可以通过worker直接访问proteced类型的成员和方法,但是不能通过wife访问proteced的成员和方法。