2021-08-10

同步异步:
同步:多个请求同时执行,前面的未得到处理,那么后面的也不会得到处理,排队(数据没有读取完不能操作数据)
异步:多个请求同时执行,互不影响(边读取边操作数据)
阻塞非阻塞:
阻塞:
同一个代码中若是阻塞,后面的代码就不会执行,只要达到某个条件后执行后面的程序(客户端连接服务器端,一直等待连接)
非阻塞:
同一个代码中这个条件没有到执行条件,也不会影响后面程序的执行(客服端没有连接到服务器端也可以执行后面的代码)
使用通道实现高效读写(通道是双向的能读也能写):

  //创建输入通道
        FileChannel is=new FileInputStream("d:/io/a.txt").getChannel();
        //创建输出通道
        FileChannel os=new FileOutputStream("d:/io/b.txt").getChannel();
        //调用方法实现传输
        is.transferTo(0, is.size(), os);
        os.close();
        is.close();

创建ByteBuffer:

//创建大小为10204的buffer缓冲区
        ByteBuffer buffer= ByteBuffer.allocate(1024);

使用ByteBuffer完成读写 方式一:

 //用缓冲区实现复制
        try {
            FileInputStream is=new FileInputStream("d:/io/a.txt");
            FileOutputStream os=new FileOutputStream("d:/io/d.txt");
            //创建缓冲区大小为1024
            ByteBuffer buffer=ByteBuffer.allocate(1024);
           //获取通道
            FileChannel ic = is.getChannel();
            FileChannel oc = os.getChannel();
            int len;
            while ((len=ic.read(buffer))!=-1){
                buffer.flip();
                oc.write(buffer);
                buffer.clear();
            }
            oc.close();
            ic.close();
            os.close();
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

方式二:

//创建大小为10204的buffer缓冲区
        ByteBuffer buffer= ByteBuffer.allocate(1024);
        //创建输入通道
        FileChannel is=new FileInputStream("d:/io/a.txt").getChannel();
        //创建输出通道
        FileChannel os=new FileOutputStream("d:/io/e.txt").getChannel();
        int len;
        while ((len=is.read(buffer))!=-1){
            //实现读写转换 重设一下buffer:limit=position(之前position的位置) , 再将位置归零position=0
            buffer.flip();
            os.write(buffer);
            buffer.clear();//重置buffer,重设position=0,limit=capacity,用于下次读取
        }
        os.close();
        is.close();

反射:

//获取Student对象的字节码文件
        //方式一 类名.class获取
//        Class<Student> clazz = Student.class;
        //方式二 对象名.getClass获取
//        Student s=new Student();
//        Class<? extends Student> clazz = s.getClass();
        //方式三 Class的静态方法forName(全限定类名)
        Class<?> clazz = Class.forName("com.itheima06.Student");
        //反射获取类中无参构造方法
//        Constructor<?> constructor = clazz.getConstructor();
        //反射获取类中带参构造方法
        Constructor<?> constructor = clazz.getDeclaredConstructor(int.class);//私有的
        Constructor<?> constructor1 = clazz.getConstructor(String.class);
        //私有的要进行暴力访问才能进行操作
        constructor.setAccessible(true);
        //根据构造方法创建对象
        Object o = constructor.newInstance(18);
        Student o1 = (Student) constructor1.newInstance("庞传钰");
        //反射获取类中所有的公有构造方法
        Constructor<?>[] constructors = clazz.getConstructors();
        for (Constructor<?> constructor2 : constructors) {
            System.out.println(constructor2);
        }
        //反射获取所有的构造方法
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            declaredConstructor.setAccessible(true);
            System.out.println(declaredConstructor);
        }
        //反射获取类中的公有方法
        Method method = clazz.getMethod("sport");
        //执行方法
        method.invoke(o);
        //获取私有的方法
        Method study = clazz.getDeclaredMethod("study",String.class);
        //暴力访问
        study.setAccessible(true);
        study.invoke(o1,o1.getName());
        //反射获取类中的公有变量
        Field age = clazz.getField("age");
        //赋值
        age.set(o1,21);
        System.out.println(age.get(o));
        //反射获取类中私有变量
        Field name = clazz.getDeclaredField("name");
        //暴力访问
        name.setAccessible(true);
        name.set(o,"小明");
        System.out.println(name.get(o));
public class Student {
    private String name;
    public int age;

    public Student(String name) {
        this.name = name;
    }

    private Student(int age) {
        this.age = age;
    }

    public Student() {
    }

    private Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    private void study(String name){
        System.out.println(name+"爱学习");
    }
    public void sport(){
        System.out.println("爱运动");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

自定义注解:
注解属性支持的数据类型有:
* 八种数据数据类型(int,short,long,double,byte,char,boolean,float)
* String,Class,注解类型,枚举类
* 以上类型的一维数组形式

  • 普通属性:
    在使用注解的时候需要为注解的属性赋值!(定义注解属性给定的是什么类型的,那么使用的时候就给这个属性赋一个该类型的值)

  • 特殊属性value:
    如果注解中只有一个属性且名字叫value,则在使用该注解时可以直接给该属性赋值,而不需要给出属性名。
    如果注解中除了value属性之外还有其他属性且只要有一个属性没有默认值,则在给属性赋值时value属性名也不能省略了。

  • 小结:如果注解中只有一个属性时,一般都会将该属性名命名为value

  • 在使用自定义注解的时候要加上元注解

    • @Target
      作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。
      可使用的值定义在ElementType枚举类中,常量值如下
      TYPE,类,接口
      FIELD, 成员变量
      METHOD, 成员方法
      PARAMETER, 方法参数
      CONSTRUCTOR, 构造方法
      LOCAL_VARIABLE, 局部变量
  • @Retention
    作用:用来标识注解的生命周期(有效范围)
    可使用的值定义在RetentionPolicy枚举类中,常用值如下
    SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
    CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
    RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

//元注解
//运行时
@Retention(RetentionPolicy.RUNTIME)
//可以定义在变量 方法和类上
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
//自定义注解
public @interface Book {
    //书名
    String name();
    //价格默认值100
    double price() default 100;
    //作者
    String writer();
}
//使用元注解
@Book(name = "斗罗大陆", writer = "唐家三少")
public class Student {
    @Book(name = "斗破苍穹", writer = "天蚕土豆",price = 200)
    String name;
    @Book(name = "伏天氏", writer = "小明")
    public void method(){
    }
}

//获取字节码对象
        Class<Student> clazz = Student.class;
        //判断这个类上有没有使用Book的注解
        if(clazz.isAnnotationPresent(Book.class)){
            //获取注解对象
            Book book = clazz.getAnnotation(Book.class);
            //获取元素输出
            System.out.println(book.name());
            System.out.println(book.price());
            System.out.println(book.writer());
        }
        //获取变量
        Field name = clazz.getDeclaredField("name");
        //判断这个变量上有没有使用Book的注解
        if (name.isAnnotationPresent(Book.class)){
            //获取注解对象
            Book book = name.getAnnotation(Book.class);
            System.out.println(book.name());
            System.out.println(book.price());
            System.out.println(book.writer());
        }
        //获取方法
        Method method = clazz.getMethod("method");
        //判断这个方法上有没有使用Book的注解
        if(method.isAnnotationPresent(Book.class)){
            //获取注解对象
            Book book = method.getAnnotation(Book.class);
            System.out.println(book.name());
            System.out.println(book.price());
            System.out.println(book.writer());
        }

动态代理
动态代理可以对被代理对象的方法进行增强,可以在不修改方法源码的情况下,增强被代理对象方法的功能,在方法执行前后做任何你想做的事情。

//定义父接口动物
public interface Animal {
    //定义方法吃
    void eat();
}

//定义狗类实现动物接口
public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
//定义猫类实现动物接口
public class Cat implements Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
 //多态创建狗对象
        Animal animal=new Dog();
        //参数一是被代理对象字节码对象的类加载器,参数二是被代理对象字节码对象的所有父接口,参数三是代理类(使用匿名内部类)
        Animal  animal1 = (Animal) Proxy.newProxyInstance(animal.getClass().getClassLoader(), animal.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                /*
                * Object proxy: 被代理对象
                * Method method:被代理对象的方法
                * Object[] args:被代理对象的参数列表
                * */
                //增强方法
                System.out.println("狗看家");
                //获取这个对象的方法
                method.invoke(animal, args);
                return null;
            }
        });
        animal1.eat();
        Animal cat=new Cat();
        Animal cat1 = (Animal) Proxy.newProxyInstance(cat.getClass().getClassLoader(), cat.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("猫抓老鼠");
                method.invoke(cat, args);
                return null;
            }
        });
        cat1.eat();
  • 动态代理非常的灵活,可以为任意的接口实现类对象做代理
  • 动态代理可以为被代理对象的所有接口的所有方法做代理,动态代理可以在不改变方法源码的情况下,实现对方法功能的增强,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。 动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
  • 动态代理同时也提高了开发效率。
  • 缺点:只能针对接口的实现类做代理对象,普通类是不能做代理对象的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值