【编程语言】Java5

day13

缓冲字节流

之前学的是基于硬盘的。

缓冲字节输出流

缓冲流实现文件的复制

每次读取到的数据的长度

缓冲字符流

输出流

copy

处理流之一:缓冲流

转换流

处理流之二:转换流

转换字节输入流为字符输入流

转换字节输出流为字符输出流

调用:类名.方法

标准输入输出流

处理流之三:标准输入输出流

标准的输入流 

练习

写静态方法是为了方便,因为可以类名.方法名调用,不用new对象。

 

调用:

打印流(了解)和数据流(了解)

打印流

数据流

数据输出流

数据输入流

对象流

序列化与反序列化针对的是对象的各种属性,不包括类的属性。

(问题?对象的各种属性不就是类的属性吗?

类属性:static修饰的,通过类名.属性获取。

对象属性:get、set调用的,通过对象.属性获取。

对象的序列化

举例

Person.java

序列化与反序列化

调用

注意

因为不在一个包内:反序列化报错!!!

随机存取流-RandomAccessFile类

RandomAccessFile类

随机读文件

随机写文件

调用:

流的基本应用小结

流是用来处理数据的。

处理数据时,一定要先明确数据源,与数据目的地。

  • 数据源可以是文件,可以是键盘。
  • 数据目的地可以是文件、显示器或者其他设备。

而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理、转换处理等。


day14

反射

大白话说Java反射:入门、使用、原理

本章主要内容

  1. 理解Class类并实例化Class类对象;
  2. 运行时创建类对象并获取类的完整结构;
  3. 通过反射调用类的指定方法、指定属性;
  4. 动态代理

人类的反射过程,看见葫芦娃3个字。

JAVA Refection:反射是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性和方法。

Java反射机制提供的功能

  1. 在运行时判断任意一个对象所属的类;
  2. 在运行时构造任意一个类的对象;
  3. 在运行时判断任意一个类所具有的成员变量和方法;
  4. 在运行时调用任意一个对象的成员变量和方法;
  5. 生成动态代理。

比如你通过AOP给每个类添加入参出参日志。你需要打印类名、方法名、入参、出参等信息。这些信息,都是通过反射获取的。

Class类

即:可以通过对象反射求出类的名称。

在Object类中定义了以下的方法,此方法就将被所有子类继承:

public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

反射可以得到的信息:某个类的属性、方法和构造方法、某个类到底实现类哪些接口。对于每个类而言,JRE都为其保留一个不变的Class类型的对象。一个Class对象包含了特定某个类的有关信息。

  • Class本身也是一个类;
  • Class对象只能有系统建立对象;
  • 一个类在JVM中只会有一个Class实例;
  • 每个类的实例都会记得自己是由哪个Class实例所生成;
  • 通过Class可以完整地得到一个类中的完整结构。
package course05;

import course02.Person;

public class Test {
    public static void main(String[] args) {
        Person p = new Person();
        //clazz对象中就包含对象p所属的Person类的所有的信息
        Class clazz = p.getClass();
        System.out.println(clazz);
        //class course02.Person
    }
}
package course02;

public class Person {
    int age;
    String name;
    int sex;

    public void showInfo(){
        System.out.println(this.age);
        System.out.println(this.name);
        System.out.println(this.sex);
    }
//    public void setInfo(int age, String name, int sex){
//        this.age = age;
//        this.name = name;
//        this.sex = sex;
//    }
}

实例化class类对象

package course05;

import course02.Person;

public class Test {
    public static void main(String[] args) {
        Person p = new Person();
        //clazz对象中就包含对象p所属的Person类的所有的信息
        Class clazz = p.getClass();
        System.out.println("clazz: " + clazz);
        //class course02.Person

        //通过类名.class创建指定类的Class实例
        Class c0 = Person.class;

        //通过一个类的实例对象的getClass()方法,获取对应实例对象的类的Class实例。
        Class c1 = p.getClass();

        try {
            //通过Class的静态方法forName(String className)来获取一个类的Class实例
            // forName(String className)方法中的参数是你要获取的Class实例的类的全路径(包名.类名)
            Class c2 = Class.forName("course02.Person");
            System.out.println("c2: " + c2);
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}

//clazz: class course02.Person
//c2: class course02.Person

反射获取一个类的父类和接口

Field、Method、Constructor、Superclass、Interface、Annotation

  • 实现的全部接口
  • 所继承的父类
  • 全部的构造方法
  • 全部的方法
  • 全部的Field

反射获取一个类的构造方法

举例:

接口

package basic05;

public interface Study {
    void studyInfo();
}
package basic05;

public interface Move {
    void moveType();
}

父类

package basic05;

public class Person {
    public String name;
    int age;
}

类&调用

package basic05;

import java.lang.reflect.Constructor;

public class Student extends Person implements Move, Study{

    String school;

    public Student(){

    }

    //main方法里,可以获取公有构造方法
    public Student(String school){
        this.school = school;
    }

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

    public void showInfo(){
        System.out.println("学校是:" + this.school);
    }

    @Override
    public void moveType() {
        System.out.println("骑自行车上学");
    }

    @Override
    public void studyInfo() {
        System.out.println("学习的中学的知识");
    }

    public static void main(String[] args) {
        try{
            //通过包名.类名的字符串,调用Class.forName方法获取指定类
            //clazz类的Class实例
            Class clazz = Class.forName("basic05.Student");

            Class superClazz = clazz.getSuperclass(); //获取父类
            System.out.println("获取父类:" + superClazz.getName());

            //获取当前类的所有接口
            Class[] interfaces = clazz.getInterfaces();
            for (Class c: interfaces
                 ) {
                System.out.println("接口:" + c.getName());
            }

            //获取构造方法
            //获取类的公有构造方法
            Constructor[] cons = clazz.getConstructors();
            for (Constructor c: cons
                 ) {
                System.out.println("公有构造方法名称:" + c.getName());
                //getModifiers取得方法的修饰符,返回数组1代表public
                System.out.println("公有构造方法名称:" + c.getName() + "的修饰符是:" + c.getModifiers());

                Class[] paramClazz = c.getParameterTypes();
                for (Class pc: paramClazz
                     ) {
                    System.out.println("公有构造方法名称:" + pc.getName() + "的参数类型是:" + pc.getName());
                }
            }

            //获取类的所有构造方法,包括公有和私有的
            Constructor[] cons1 = clazz.getDeclaredConstructors();
            for (Constructor c: cons1
                 ) {
                System.out.println("-------------------------");
                System.out.println("构造方法名称:" + c.getName());
                //1为public,2为private
                System.out.println("构造方法名称:" + c.getName() + "的修饰符是:" + c.getModifiers());

                //获取构造方法的参数类型,有几个参数数组的元素就有几个
                Class[] paramClazz = c.getParameterTypes();
                for (Class pc: paramClazz
                     ) {
                    System.out.println("构造方法名称:" + pc.getName() + "的参数类型是:" + pc.getName());
                }

                System.out.println("--------------------------------");
            }



        } catch (ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}
/*
获取父类:basic05.Person
接口:basic05.Move
接口:basic05.Study
公有构造方法名称:basic05.Student
公有构造方法名称:basic05.Student的修饰符是:1
公有构造方法名称:java.lang.String的参数类型是:java.lang.String
公有构造方法名称:basic05.Student
公有构造方法名称:basic05.Student的修饰符是:1
-------------------------
构造方法名称:basic05.Student
构造方法名称:basic05.Student的修饰符是:2
构造方法名称:java.lang.String的参数类型是:java.lang.String
构造方法名称:int的参数类型是:int
--------------------------------
-------------------------
构造方法名称:basic05.Student
构造方法名称:basic05.Student的修饰符是:1
构造方法名称:java.lang.String的参数类型是:java.lang.String
--------------------------------
-------------------------
构造方法名称:basic05.Student
构造方法名称:basic05.Student的修饰符是:1
--------------------------------

Process finished with exit code 0

 */

通过反射创建一个对象

调用构造方法能干什么呢?

package basic05;

import java.lang.reflect.Constructor;

public class Student2 extends Person implements Study, Move{

    String school;

    public Student2(){
        System.out.println("调用的是public Student()");
    }

    //main方法里,可以获取公有构造方法
    public Student2(String school){
        this.school = school;
        System.out.println("调用的是public Student2(String school)");
    }

    private Student2(String name, int age){
        this.name = name;
        this.age = age;
        System.out.println("调用的是private Student2(String name, int age)");
    }

    public void showInfo(){
        System.out.println("学校是:" + this.school);
    }

    @Override
    public void moveType() {
        System.out.println("骑自行车上学");
    }

    @Override
    public void studyInfo() {
        System.out.println("学习的中学的知识");
    }


    public static void main(String[] args) {
        try {
            //clazz类的Class实例
            Class clazz = Class.forName("basic05.Student2");
            //如果用反射的构造方法来创建对象
//            Object obj = clazz.newInstance(); //相当于调用Student类的无参公有构造方法
//            Student2 stu = (Student2) obj;

            //指定获取有一个参数并且为String类型的公有构造方法
            Constructor c = clazz.getConstructor(String.class);
            //newInstance实例化对象,相当于调用public Student2(String school);
            Student2 stu1 = (Student2)c.newInstance("第一中学");
            System.out.println("stu1:" + stu1.school);

            System.out.println("--------------------------------------");
            //通过反射机制,可以强制的调用私有的构造方法
            //获取有两个参数的构造方法
            Constructor c1 = clazz.getDeclaredConstructor(String.class, int.class);
            //接触私有的封装,下面就可以对这个私有方法强制调用
            Student2 stu = (Student2)c1.newInstance("zhangsan", 12);
            System.out.println("stu:" + stu.name + "+" + stu.age);

        }catch (Exception e){
            e.printStackTrace();
        }

    }
}
/*
调用的是public Student2(String school)
stu1:第一中学
--------------------------------------
调用的是private Student2(String name, int age)
stu:zhangsan+12
 */

反射机制获取类的方法

student新增方法

main方法里

反射机制获取类的属性和包

student新增属性

属性

反射机制调用指定方法

stuent新增方法

main里指定调用

调用重载方法

和有返回值的方法

main调用  ...是0到多个的意思

第一中学是这里来的

反射机制调用指定属性

共有的属性

私有的属性

java动态代理(反射的关键应用)

Proxy:专门完成代理的操作类,是所有动态代理类的父类。通过此类为一个或多个接口动态地生成实现类。

先要做个接口

package basic05.ProxyDemo;

public interface ITestDemo {
    void test1();
    void test2();
}

实现类

main里

被代理的对象是test,返回object,是成功被代理后的对象。

动态代理类

  

动态代理步骤

  1. 创建一个实现接口InvocationHandler的类,它必须实现invoke方法,以完成代理的具体操作;
  2. 创建被代理的类以及接口;
  3. 通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 创建一个Subject接口代理;
  4. 通过Subject代理调用RealSubject实现类的方法。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值