java自学之路二十二(jdk新特性二)

补充

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特有功能

  1. public void addElement(object,obj)
  2. public object elementAt(int index)

特有功能被get add 取代

TreeSet

能够对元素按照某种规则进行排序

  1. 自然排序

    真正的比较依赖于元素的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);
        }
    }
    
  2. 比较器排序

类加载器

负责将.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文件对象的方式

  1. 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());
    
    }
    
  2. 点class方法

    System.out.println(Person.class == p1.getClass());
    
  3. 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(包括父类的)

    1. 实例化对象
    2. 获取成员方法
    3. 用对象来调用成员方法
    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();

注意:

  1. 定义枚举类要用关键字enum
  2. 所有枚举类都是Enum的子类
  3. 枚举类第一行必须是枚举项
  4. 枚举类可以有构造器,但必须是private,默认也是private的
  5. 枚举类也可以有抽象方法,但是必须重写该方法

常用方法

  • 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);
    }
原文地址:https://www.cnblogs.com/jimmyhe/p/12367902.html