补充
Math补充
e 自然对数的底数,pi 圆周率,pow幂函数
BigDecimal
进行浮点数计算
public static void main(String[] args) {
System.out.println(0.09+0.01);
BigDecimal bd1 = new BigDecimal("0.09");
BigDecimal bd2 = new BigDecimal("0.01");
System.out.println(bd1.add(bd2));
}
Vector特有功能
- public void addElement(object,obj)
- public object elementAt(int index)
特有功能被get add 取代
TreeSet
能够对元素按照某种规则进行排序
-
自然排序
真正的比较依赖于元素的compareTo()方法,而这个方法是定义在comparable里面的,所以要重写该方法,就必须是先comparable接口,这个接口表示自然排序
利用二叉树保证元素的大小和唯一性
public class DemoTreeSet { public static void main(String[] args) { TreeSet<Integer> ts = new TreeSet<>(); ts.add(20); ts.add(18); ts.add(23); ts.add(20); ts.add(17); System.out.println(ts); } }
-
比较器排序
类加载器
负责将.class文件加载到内存中,并为之生成对应的Class对象
组成:
-
Bootstrap ClassLoader 根类加载器
引导类加载器,负责java核心类的加载,比如system,string等在JDK中JRE的lib下rt.jar文件中
-
Extension ClassLoader 扩展类加载器
负责jre扩展目录中jar包的加载
-
System ClassLoader 系统类加载器
负责在jvm启动时加载来自java命令的class文件,以及classpath环境变量指定的jar包和类路径
反射
通过class文件对象,去使用该文件中的成员变量Field,构造方法Constructor,成员方法Method
获取class文件对象的方式
-
Object类的getClass()方法
public static void main(String[] args) { Person p1 = new Person("janice",32); Person p2 = new Person("hawi",13); System.out.println(p1 == p2); System.out.println(p1.getClass() == p2.getClass()); }
-
点class方法
System.out.println(Person.class == p1.getClass());
-
Class类中的静态方法
Class c4 = Class.forName("practice2.demo.demo1012.Person"); // 必须是包的全路径 System.out.println(c4 == Person.class);
获取公共构造方法
Constructor[] constructors = c4.getConstructors();
for(Constructor c:constructors){
System.out.println(c);
}
public practice2.demo.demo1012.Person()
public practice2.demo.demo1012.Person(java.lang.String,int)
注意:getDeclaredConstructors获取所有构造方法,包括无public修饰和private私有
Constructor[] constructors1 = c4.getDeclaredConstructors();
for(Constructor c:constructors1){
System.out.println(c);
}
获取单个构造方法
参数表示的是:要获取的构造方法的构造参数个数己数据类型的class字节码文件对象
获得构造方法对象后可以用来创建该构造方法的声明类实例,并用指定的参数初始化该实例。
Constructor c4Constructor = c4.getConstructor(); // 获取无参数构造方法
Object obj = c4Constructor.newInstance();
System.out.println(obj);
Constructor c4Constructor1 = c4.getConstructor(String.class, int.class); // 带参数构造方法
Object obj2 = c4Constructor1.newInstance("23",34);
System.out.println(obj2);
获取私有构造方法
getDeclaredConstructor() 获取所有构造方法
IllegalAccessException 非法的访问异常(访问类的私有方法)
解决:con.SetAccessible(true) // con是获取的构造方法
通过反射获取成员变量并使用
同上,具有获取私有成员变量和公共成员变量的功能以及单个成员变量
Field[] fields = c4.getDeclaredFields();
for(Field i:fields){
System.out.println(i);
}
Field name = c4.getDeclaredField("name");
Constructor constructor = c4.getConstructor();
Object obj = constructor.newInstance();
name.setAccessible(true);
name.set(obj,"hhh");
System.out.println(obj);
c4是类对象,类对象可以获得成员变量,构造方法,成员方法
con是构造器,可以构造对象
获取的field 对象 setAccessible
获取成员方法
-
获取所有方法
getMethods(包括父类的)
- 实例化对象
- 获取成员方法
- 用对象来调用成员方法
Object obj = c.getConstructor().newInstance(); // getMethod(String name, Class<?>... parameterTypes) Method m1 = c.getMethod("show") // public Object invoke(Object obj, Object...args) 返回值是Object接收,第一个参数表示对象是谁,第二个参数表示调用该方法的实际参数 m1.invoke(obj) 本质是调用obj对象的m1方法
, getDeclaredMethods
-
获取单个方法
getMethod, getDeclaredMethod
-
暴力访问
method.setAccessible(true)
往泛型是Integer的ArrayList中放String
注意:泛型是给编译器看的,实际上jvm运行中按照obj来处理
所以可以用反射来获取add方法,自定义添加数据类型
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<Integer> arr = new ArrayList<>();
Class<? extends ArrayList> c = arr.getClass();
Method m1 = c.getMethod("add",Object.class);
m1.invoke(arr,"hello");
arr.add(3);
System.out.println(arr);
}
// [hello, 3]
动态代理
Java.lang.reflect.Proxy
Proxy提供用于创建动态代理类和实例的静态方法,它是由这些方法创建的所有动态代理的超类。
主程序:
public static void main(String[] args){
User user = new UserImpl();
user.add();
user.del();
user.update();
user.list();
// 想对谁做代理传谁
MyInvocationHandler handler = new MyInvocationHandler(user);
User proxy = (User)Proxy.newProxyInstance(
user.getClass.getClassLoader, // 类加载器
user.getClass.getInterface, // 接口类
handler
) // 可以用Object对象接受,实际上是User对象
proxy.add()
proxy.del()
proxy.update()
proxt.list()
}
public class MyInvocationHandler implements InvocationHandler {
private Object target; // 目标对象
public MyInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置处理");
Object result = method.invoke(target, args);
System.out.println("后置处理");
return result; // 返回的是代理对象
}
}
枚举
将变量的值一一列出来,变量的值只限于列举出来的值的范围内
一、
注意:抽象类不能实例化
public enum Dirction {
FRONT,BEHIND,LEFT,RIGHT
}
打印直接调用toString方法而不是地址值
二、引用成员变量
public enum Direction2 {
FRONT("前"),
BEHIND("后"),
LEFT("左"),
RIGHT("右");
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
Direction2(String name) {
this.name = name;
}
}
Direction2 front = Direction2.FRONT;
System.out.println(front.getName());
三、抽象方法
public enum Direction3 {
FRONT("前"){
@Override
public void show() {
System.out.println("1");
}
},
BEHIND("后"){
@Override
public void show() {
System.out.println("2");
}
},
LEFT("左"){
@Override
public void show() {
System.out.println("3");
}
},
RIGHT("右"){
@Override
public void show() {
System.out.println("4");
}
},;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
Direction3(String name) {
this.name = name;
}
public abstract void show();
}
Direction3 behind1 = Direction3.BEHIND;
behind1.show();
注意:
- 定义枚举类要用关键字enum
- 所有枚举类都是Enum的子类
- 枚举类第一行必须是枚举项
- 枚举类可以有构造器,但必须是private,默认也是private的
- 枚举类也可以有抽象方法,但是必须重写该方法
常用方法
- compareTo,枚举的顺序
Direction2 d21 = Direction2.FRONT;
Direction2 d22 = Direction2.BEHIND;
Direction2 d23 = Direction2.LEFT;
Direction2 d24 = Direction2.RIGHT;
System.out.println(d21.compareTo(d24));
-
Ordinal,返回枚举的序数
System.out.println(d22.ordinal());
-
valuesOf
Direction2 d = Enum.valueOf(Direction2.class,"FRONT"); System.out.println(d.getName());
-
values() 遍历枚举项的枚举值
Direction2[] dirs = Direction2.values(); for(Direction2 dir:dirs){ System.out.println(dir.getName()); }
JDK7新特性
二进制,十六进制,八进制字面量
public static void main(String[] args) {
int x = 0b101010;
System.out.println(x);
int y = 0x1001;
System.out.println(y);
int z = 01101;
System.out.println(z);
}
下划线当作数字分隔符
int x = 100_1000;
System.out.println(x);
try改进
将需要关闭的资源放在try后面的小括号里,必须是java.lang.AutoCloseable子类对象
大部分流体系的对象是这个接口的子类
try(FileReader fr = new FileReader(a.txt));
FileWriter = fw = new FilwWriter(b.txt);){
while((ch = fr.read()) != -1){
fw.writer(ch)
}cathc(IoException e){
e.printStackTrace();
})
}
JDK8新特性
在接口类中可以定义默认方法和静态方法
Optional类
是一个容器类,可以保存类型T的值,代表这个值存在,或者仅仅保存null,表示不存在。 避免空指针异常。
public String getBoyName(Girl girl){
Optional<Girl> girl1 = Optional.ofNullable(girl);
Girl girl2 = girl1.orElse(new Girl(new Boy("kawii")));
Boy boy = girl2.getBoy();
Optional<Boy> boy1 = Optional.ofNullable(boy);
Boy boy2 = boy1.orElse(new Boy("kawii2"));
girl2.setBoy(boy2);
System.out.println(girl1);
// Girl girl2 = girl1.orElse(new Girl(boy2));
return girl2.getBoy().getName();
}
@Test
public void test3(){
// Girl girl = new Girl();
Girl girl = null;
String boyName = getBoyName(girl);
System.out.println(boyName);
}