目录
3.1、Object
描述:该类是所有类的最终根类。
如何实现对象的深拷贝?
public class Person implements Serializable {
private static final long serialVersionUID = -7466779555039906117L;
private String name;
private Integer age;
private Person friend;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Person getFriend() {
return friend;
}
public void setFriend(Person friend) {
this.friend = friend;
}
public Person deepClone() {
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
return (Person) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
ois.close();
bis.close();
oos.close();
bos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
3.2、Class
描述:在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
如何获取一个class的Class实例?有三个方法:
方法一:直接通过一个class的静态变量class获取:
Class cls = String.class;
方法二:如果我们有一个实例变量,可以通过该实例变量提供的getClass()
方法获取:
String s = "Hello";
Class cls = s.getClass();
方法三:如果知道一个class
的完整类名,可以通过静态方法Class.forName()
获取:
Class cls = Class.forName("java.lang.String");
因为Class实例在JVM中是唯一的,所以,上述方法获取的Class实例是同一个实例。
- 用instanceof不但可以匹配指定类型,还可以匹配指定类型的子类
- 用==判断class实例可以精确地判断数据类型,但不能作子类型比较
由于JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该class的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段等,因此,如果获取了某个Class实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息。这种通过Class实例获取class信息的方法称为反射(Reflection)。
参考:idea :a116xia
反射创建新的实例:
方法 | 描述 |
public T newInstance() | 创建新的实例 |
构造器创建对象
//1.先获取Uesr的Class对象
Class<?> c = Class.forName("a000001.User");
//2.通过public的无参构造器创建实例
Object o = c.newInstance();
System.out.println(o);
//3.通过public的有参构造器创建实例
//3.1先得到构造器
//3.2创建实例,并传入实参
Constructor<?> constructor = c.getConstructor(String.class);
Object o1 = constructor.newInstance("wrg");
System.out.println(o1);
//4.通过非public的有参构造器创建实例
//4.1先得到私有的构造器对象
//4.2创建实例
Constructor<?> declaredConstructor = c.getDeclaredConstructor(new Class[]{int.class, String.class});
declaredConstructor.setAccessible(true);
Object wrg2 = declaredConstructor.newInstance(20,"wrg2");
System.out.println(wrg2);
反射获取资源文件:
方法 | 实例 |
cls.getResourceAsStream("aa.txt"); | 获取编译后Class文件同级目录的aa.txt |
cls.getClassLoader().getResourceAsStream("bb.txt"); | 获取编译后ClassPath目录下的bb.txt |
反射获取构造方法:
反射获取成员变量:
反射获取成员方法:
反射获取类上注解:
反射获取类上信息:
反射判断数据类型:
3.3、System
描述:在 System 类提供的设施中,有标准输入、标准输出和错误输出流;对外部定义的属性和环境变量的访问;加载文件和库的方法;还有快速复制数组的一部分的实用方法。
3.4、Math
描述:Math 类包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数。
两个常量值:
- public static final double E = 2.7182818284590452354;
- public static final double PI = 3.14159265358979323846;
3.5、Number
描述:抽象类 Number 是Byte、Short、Integer、Long、Float、Double、BigInteger、BigDecimal等类的父类。
3.6、包装类
自动装箱:把基本数据类型转换为对应的包装类型
例如:Integer total = 99;
对应:Integer total = Integer.valueOf(99);
自动拆箱:把包装类型转换为对应的基本数据类型
例如:int totalprim = total;
对应:int totalprim = total.intValue();
Integer类:
3.7、大数字
BigInteger类:
BigInteger bi1 = new BigInteger("100");
BigInteger bi2 = new BigInteger("50");
// public BigInteger add(BigInteger val):加
System.out.println("add:" + bi1.add(bi2));
// public BigInteger subtract(BigInteger val):减
System.out.println("subtract:" + bi1.subtract(bi2));
// public BigInteger multiply(BigInteger val):乘
System.out.println("multiply:" + bi1.multiply(bi2));
// public BigInteger divide(BigInteger val):除
System.out.println("divide:" + bi1.divide(bi2));
BigDecimal类:
BigDecimal bd1 = new BigDecimal("0.09");
BigDecimal bd2 = new BigDecimal("0.01");
// public BigDecimal add(BigDecimal val):加
System.out.println("add:" + bd1.add(bd2));
BigDecimal bd3 = new BigDecimal("1.0");
BigDecimal bd4 = new BigDecimal("0.32");
// public BigDecimal subtract(BigDecimal val):减
System.out.println("subtract:" + bd3.subtract(bd4));
BigDecimal bd5 = new BigDecimal("1.015");
BigDecimal bd6 = new BigDecimal("100");
// public BigDecimal multiply(BigDecimal val):乘
System.out.println("multiply:" + bd5.multiply(bd6));
BigDecimal bd7 = new BigDecimal("1.301");
BigDecimal bd8 = new BigDecimal("100");
// public BigDecimal divide(BigDecimal val):除
System.out.println("divide:" + bd7.divide(bd8));
3.8、String
描述:String 类代表字符串。
构造方法:
成员方法:
注意事项:
3.9、Throwable
异常体系:
常见异常:
处理异常:
解决方案一:用try-catch常规的方式处理异常
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
} finally {
释放资源的代码;
}
解决方案二:用try-catch新特性方式处理异常
try (定义流对象;定义流对象....) {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
解决方案三:用throws方式抛出异常
public void 方法名() throws 异常类名 {
}
解决方案四:用throw方式抛出异常
public void 方法名() {
//...
//抛出异常
throw new 异常类名(异常信息);
//...
}
注意事项:
3.10、Lambda
Lambda的简介:
Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。虽然使用 Lambda 表达式可以对某些接口进行简单的实现,但并不是所有的接口都可以使用 Lambda 表达式来实现。Lambda 表达式规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法,被 default 修饰的方法会有默认实现,不是必须被实现的方法,所以不影响 Lambda 表达式的使用。
Lambda的标准语法:
标准格式:
(参数类型 参数名称) -> {
代码体;
}
无参无返回值抽象方法练习:
interface MyInter {
void show();
}
public class Main {
public static void main(String[] args) {
myInterShow(() -> {
System.out.println("Hello,World");
});
}
public static void myInterShow(MyInter mi) {
mi.show();
}
}
有参无返回值抽象方法练习:
interface MyInter {
void show(String s);
}
public class Main {
public static void main(String[] args) {
myInterShow((String s) -> {
System.out.println(s);
});
}
public static void myInterShow(MyInter mi) {
mi.show("Hello,World");
}
}
有参有返回值抽象方法练习:
interface MyInter {
int show(int x, int y);
}
public class Main {
public static void main(String[] args) {
myInterShow((int x, int y) -> {
return x + y;
});
}
public static void myInterShow(MyInter mi) {
int show = mi.show(10, 20);
System.out.println(show);
}
}
Lambda的简化语法:
- 小括号内的参数类型可以省略,但是有多个参数的情况下,不能只省略一个
- 如果小括号内有且仅有一个参数,则小括号可以省略
- 如果大括号内有且仅有一个语句,则可以同时省略大括号、return关键字及语句分号
Lambda表达式和匿名内部类的区别:
1、所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda表达式:只能是接口
2、使用限制不同
- 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
3、实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件,对应的字节码会在运行的时候动态生成