zoukankan      html  css  js  c++  java
  • Java小结

    1. 反射

    java数据类型分为原始类型和引用类型。对于每种类型的对象java虚拟机会实例化不可变的java.lang.Class对象,它提供了在运行时检查对象属性的方法,这些属性包括它的成员和类型信息。

    注:Class是泛型类,可以使用@SuppressWarnings("unchecked")忽略泛型或者使用Class<?>类型,?表示任意类型。

    • 获取class对象的五种方法

      • Object.getClass():如果一个类的对象可用,则最简单的获的Class的方法是使用Object.getClass()(只对引用类型有用);
      • .class:若果类型可用但没有对象,可以在类型后加上".class"来获的Class对象;
      • Class.forName():如果知道类的全名,可使用静态方法Class.forName来获的Class对象,但它不能用在原始类型上,抛出ClassNotFoundException异常;
      • 包装类的Type域:每个原始类型和void都有包装类,利用其Type域就可以获的Class对象(注:Double Integer分别是double以及int的包装类);
      • 以Class返回值得方法:参考反射API。
    • getName的返回值

    对不同类型的对象或类,class对象的名称是不同的,从这个名称就可以判断原来类型的,所有数组对象都有"["。具体返回值为:

    如果此类对象表示的是非数组类型的引用,则返回该类的二进制名称(如java.lang.Class);

    如果此类对象表示一个基本类型(如int,long)或void,则返回的名字是一个基本类型或void所对应的java语言关键字相同的字符串;

    如果此类对象表示一个数组,名字的内部形式为:表示该数组嵌套深度的一个或多个"["字符加元素类型名,元素类型名的编码为:

    元素类型

    编码

    元素类型

    编码

    元素类型

    编码

    boolen

    Z

    int

    I

    char

    C

    byte

    B

    float

    F

    long

    J

    double

    D

    short

    S

    class or interface

    LclassName

       

       

    //1. 获得引用类型名称

    String dateName = new Date().getClass().getName();// 对象获的Clas对象

    String dateClassName = Date.class.getName();//类获的Class对象

    String dateClassForName = Class.forName("java.util.Date").getName();

    --他们都返回类的二进制名称:java.util.Date

    //2. 获得原始类型名称

    String byteName = int.class.getName();// 获得原始类型名称

    --返回值为int

    //3. 引用类型数组

    String oneDimensionArray = new Date[4].getClass().getName();

    --一维:[Ljava.util.Date

    String twoDimensionArray = new int[4][4].getClass().getName();

    --二维:[[I

    1. 查看类声明

    通常类的声明包括常见修饰符(public,protected,private,abstract,static,final) 类的名称、类的泛型参数、类的继承类(实现的接口)、类的注解等信息。

    Class类的实例表示正在运行的java应用程序中的类和接口。枚举是一个类,注释是一个接口,每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。

    Class类常用方法:

    注:Java语言预定义的注解只有@Deprecated可以在运行时获得。

       

    Class<?> clazz = Class.forName("java.util.ArrayList");// 获得ArrayList类对象

    // 1. 输出类的泛型参数

    TypeVariable<?>[] typeVariables = clazz.getTypeParameters();

    // 2. 输出类所实现的所有接口

    Type[] interfaces = clazz.getGenericInterfaces();

    //3. 输出类的直接继承类,如果是继承自Object则返回空

    Type superClass = clazz.getGenericSuperclass();

    //4. 输出类的所有注释信息,有些注释信息是不能用反射获得的

    Annotation[] annotations = clazz.getAnnotations();

    一、Type类型

    Type是Java编程语言中所有类型的普通的父接口。这些类型包括原生类型(raw types),参数化类型(parameterized types),数组类型(array types),类型变量(type variables)和 原始类型(primitive types)。我们一般不直接操作Type类型,但了解一下Type类型的层次结构还是有必要的。

    1、Type层次结构

       

    2、Class,Method和Field的继承体系

       

    在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息保存着每个对象所属的类足迹。虚拟机利用运行时信息选择相应的方法执行。然而,可以通过专门的Java类访问这些信息。保存这些信息的类称为Class,泛型形式为Class。Class是反射机制的基础,反射API通过操作Class来获取其完整结构。

    1. 查看类成员

    类的成员包括成员变量、方法、构造器以及内部类等,常用方法如下:

    另:getDeclaredClasses() 返回该对象的内部类

    classObject.getDeclareField("域的字符串形式")

    getDeclareField与getField区别:前者获取所有成员变量,后者只获取public成员变量。

    Class<?> clazz = Class.forName("java.util.ArrayList");// 获得ArrayList类对象

    //1. 获得该类对象的所有构造方法

    Constructor[] constructors = clazz.getConstructors();

    //2. 获得该类对象的所有非继承域

    Field[] fields = clazz.getDeclaredFields();

    //3. 获得该类对象的所有非继承方法

    Method[] methods =clazz.getDeclaredMethods();

    1. 按继承层次对类排序

    Class类中的isAssignableFrom方法用来判断当前Class对象所表示的类与给定的Class对象所表示的类之间的关系,如果相同或者是其父类,则返回true,如clazz1.isAssignableFrom(clazz2) 若clazz1是否是clazz2父类

    排序:

    TreeSet<E>是基于TreeMap的NavigableSet实现的,它使用元素的自然顺序或创建TreeSet<E>对象时提供的Comparator对元素进行排序。

    //重写Comparator接口指定其泛型类型为Class<?>

    public class ClassComparator implements Comparator<Class<?>> {

    @Override

    // 通过实现Comparator接口来实现比较功能

    public int compare(Class<?> clazz1, Class<?> clazz2) {

    if (clazz1.equals(clazz2)) {// 如果两个类对象相同则返回0

    return 0;

    }

    if (clazz1.isAssignableFrom(clazz2)) {

    return -1; // 如果clazz1所表示的类是clazz2所表示的类的父类则返回-1

    }

    if (clazz2.isAssignableFrom(clazz1)) {

    return 1; // 如果clazz1所表示的类是clazz2所表示的类的子类则返回1

    }

    throw new IllegalArgumentException("两个类之间没有关系");// 其他情况抛出异常

    }

    }

    //创建TreeSet对象时指定排序方式,以及确定泛型为Class<?>

    TreeSet<Class<?>> treeSet = new TreeSet<Class<?>>(new ClassComparator())

    treeSet.add(JPanel.class);// 向树集中添加JPanel.class

    System.out.println(treeSet.last());// 获得树集的最后一个元素

    1. 动态设置类的私有域

    Field类提供有关类或接口的的单个字段信息,以及对他的动态访问权限,反射的字段可能是一个类(静态)字段或实例字段。Field类常用方法有:

    注:对于私有域,首先要用setAccessible()将其可见性设置为true才能设置新值。

    在set(Object obj,Object value)函数中,obj为字段所在的对象,若为静态字段,则obj为null,value为设置的值。

       

    Student student =new Student(); //创建实例对象

    Class<?> stuClass = student.getClass();//获取反射对象

    Field accountField = stuClass.getDeclaredField("account");//获取指定字段的值

    accountField.setAccessible(true);//字段的可见性设为true

    accountField.set(student, 200);//设置值为200

    accountField.setDouble(student, 300);

    System.out.println(student.getAccount());

    1. 动态调用类中的方法

    Java中调用类的方法有两种方式:对于静态方法,可以直接使用类名调用,对于非静态方法,必须使用类的对象调用。

    Method类提供类或接口上单独某个方法(以及如何方法该方法)的信息。它通过public Object invoke(Object obj, Object …args)调用方法,obj为方法所在的对象,静态方法为null,…args为参数,返回值为Object类型。

    1.获取指定名称的无参数方法

    Method showMethod = stuClass.getDeclaredMethod("show");

    2.调用指定对象的无参方法

    showMethod.invoke(student);

    3.获取指定名称的方法,后面的参数是参数的类型

    Method showInfo = stuClass.getDeclaredMethod ("showInfo",String.class,int.class);

    4.调用指定参数的方法,后面的参数是参数的值,要与参数类型相对应

    String rString=(String)showInfo.invoke(student,"DSL",20);

    1. 动态实例化对象

    java通常使用构造方法来创建对象,构造方法分为有参数和无参数两种,如果类中没有定义构造方法,编译器会自动添加一个无参数的构造方法。Constructor类提供类的单个构造方法的信息以及对它访问权限。它允许在将实参与带有底层构造方法的形参的newInstrance()匹配时进行转换。

    public T newInstance(Object …args)

    //获取类的无参数构造器属性

    Constructor<Student> constructor = Student.class.getDeclaredConstructor();

    //调用无参数的构造器创建对象

    Student studentCreate = constructor.newInstance();

    //获取类的有参数构造器属性

    Constructor<Student> constructorArgs = Student.class.getDeclaredConstructor(String.class,int.class,double.class);

    //传入参数创建对象

    Student studentCreateArgs = constructorArgs.newInstance("DSL",28,7000);

    1. 创建可变长度数组

    ArrayList可以动态添加和删除数组。

    Array提供了动态创建和访问java数组的方法,允许在执行get或set操作期间进行扩展转换,它也提供获取/删除指定位置元素的方法。

    对于Class类实例,classObject.isArray()判断classObject是否是数组类型。

    public static Object increaseArray(Object array) {

    Class<?> clazz = array.getClass();// 获得代表数组的Class对象

    if (clazz.isArray()) {// 判断其对应的类型是否是数组

    // 获得数组元素的类型

    Class<?> componentType = clazz.getComponentType();

    int length = Array.getLength(array);// 获得输入的数组的长度

    // 新建数组指定数组元素类型以及长度,创建新的数组对象

    Object newArray = Array.newInstance(componentType, length + 5);

    System.arraycopy(array, 0, newArray, 0, length);// 复制原来数组中的所有数据

    return newArray;// 返回新建数组

    }

    return null;// 如果输入的不是数组就返回空

    }

    1. 反射与动态代理

    使用代理可以在运行时创建一个实现了一组给定接口的新类,这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用。

    Invocationhandler接口是代理实例的调用处理程序实现的接口,对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的invoke()方法,该方法声明如下:

    Object invoke(Object proxy,Method method,Object[] args)

    method:所代理的代理类中的方法,由代理类调用其方法时传入

    args:代理类方法的参数,由代理类代用其方法时传入

    Poxy接口提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。本实例使用该接口中定义的newProxyInstance()方法获的一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。

    public static Object newProxyInstance(ClassLoader loader,Class<?> interfaces, InvocationHhandler)

    loader:定义代理类的类加载器;

    interfances:一个Class对象数组,代理类要实现的接口列表;

    InvocationHander:指派方法调用的调用处理程序。

    分别通过接口实现以及代理实现接口Seller:

    public interface Seller {

    void sell();// 简单的测试方法

    }

    普通方法:

    public class HouseSeller implements Seller {

    // 实现接口的方法,用输出来区别该类

    public void sell() {

    System.out.println("销售人员在卖房子"); }

    }

       

    //在main方法中调用,创建对象,在调用方法

    Seller seller = new HouseSeller();

    eller.sell();// 普通方式调用sell()方法

       

    通过代理实现接口

    //1.首先实现InvocationHandler接口,并重写invoke方法,用Proxy创建的代理类实例无论调用什么方法都是在调用Agency中的 invoke()方法

    public class Agency implements InvocationHandler {

    private Object target;//在构造函数中赋值

    /// 用来处理代理类,正真实现代理类的方法

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    System.out.println("代理人员在卖房子");

    //在此处正真调用target中的method方法,要求target实现Seller接口

    method.invoke(target,args);

    return null;

    }

    }

       

    //在main函数中

    // 获得接口Seller类的类加载器

    ClassLoader loader = Seller.class.getClassLoader();

    //生成代理类实例

    seller = (Seller) Proxy.newProxyInstance(loader, new Class[] { Seller.class }, new Agency());

    seller.sell();// 代理方式调用sell()方法,其实在调用Agency中的invoke方法

    seller.sell(100,"DSL")//有参数的方法

    1. 异常

      1. 异常分类

    所有异常都是由Throwable继承而来,在下一层分解为两个分支:Error和Exception。

    • Error类层次结构描述了java运行时系统内部错误和资源耗尽错误(无力解决)。
    • Exception类层次分为两个分支,如下:
    • 程序自身错误导致的异常属于RuntimeException,包括错误的类型转换、数组访问越界、访问空指针、除数为零等。
    • 程序本身没有问题,但由于像I/O错误这类问题导致的异常属于其他异常,如试图在文件尾部后面读取数据、试图打开一个不存在的文件等。

    未检查异常(unchecked):派生于Error类或RuntimeException类的所有异常称;

    已检查(checked):所有其他的异常。

    1. 声明已检查异常

    方法上抛出异常:一个方法必须声明所有可能抛出的已检查异常,这样可以从首部反映出这个方法可能抛出哪类已检查异常(如果暂时不处理这些异常)。当重写继承的方法时,抛出的异常不能比超类的范围大,或者不抛出异常。

    public Image loadImage(String s) throws FileNotFoundException,EOFException

    {

    }

    方法中抛出异常:对于系统预定义的异常,一般至少有两个构造方法,即空参数构造方法和字符串参数构造方法。使用字符串参数构造方法可以让用户为该构造方法增加提示信息。

    public Image loadImage(String s)

    {

        throw FileNotFoundException("Hello world")

    }

    1. 自定义异常类

    自定义异常类派生于Exception或它的子类,包含两个构造函数,可以用getMessage()获取传入的信息:

    class FileFormatException extends IOException

    {

        pubic FileFormatException()

        {

        }

        public FileFormatException(String str)

        {

            super(str);

        }

    }

    1. 捕获异常

    如果某个异常发生的时候没有在任何地方进行捕获,那程序就会终止执行,并在控制台上打印出异常信息,其中包括异常的类型和堆栈信息。如果调用了一个抛出已检查异常的方法,就必须对它进行处理,或者通过throws/throw将它继续进行传递。

    通过try/catch/finally语句块捕获异常。

    1. 再次抛出异常与异常链

    在catch子句中可以抛出一个异常,这样做的目的是改变异常的类型,如将SQLException异常转为ServletException异常:

    try{…}

    catch(SQLException e)

    {

        throw new SerleException("database error:"+e.getMesssage());//再次抛出异常

    }

    将原始异常设置为新异常的"原因":

    new SerleException("database error").initCause(e).

    重新获取原始异常:Throwable e = se.getCause();

    1. finally子句

    不管是否有异常被捕获,finally子句中的代码被执行。

    问题:当finally与try同时发生异常时,finally中抛出的异常会覆盖try中抛出的异常。

    try{…}

    finally

    {

        in.close();

    }

    finally子句包含return语句时。假设利用return语句从try语句块中退出。在方法返回前,finally子句的内容将被执行,如果finally子句中也有一个return语句,这个返回值将会覆盖原始的返回值,如下例,返回值为8

    try{

        return 4;

    }

    finally

    {

        return 8;

    }

    1. 带资源的try语句

    Java SE 7的AutoCloseable接口有一个方法:

    void close() throws Exception;

    假设资源属于一个实现了AutoCloseable接口的类,可以用带资源的try语句(try-with-resources),它会自动关闭资源:

    try(Scanner in = newScanner(new FileInputStream("/usr/share.dict"),

    PrintWriter out = new PrintWriter("out.txt"))

    {

       

    }

    不论这个块如何退出,in和out都会关闭。带资源的try语句可以使原来try中的异常重新抛出,而close方法抛出的异常会"被抑制"。

    1. 分析堆栈跟踪元素

    堆栈跟踪(stack trace)是一个调用过程的列表,它包含了程序执行过程中方法调用的特定位置。

    Throwable类的printStackTrace()方法访问堆栈跟踪的文本信息,显示异常类型、异常信息、异常发生位置;

    getMessage ()获取传入异常类的异常信息;

    StackTraceElemen类含有能够获得文件名、类名、方法名和当前执行的代码行号;

    Throwable t = new Throwable();

    StackTraceElement[] frames = t.getStackTrace();

    for (StackTraceElement f : frames)

    System.out.println(f);

    静态的Thread.getAllStackTrace方法,它可以产生所有线程的堆栈跟踪。

    从各处转载java文件
  • 相关阅读:
    Why Choose Jetty?
    Jetty 的工作原理以及与 Tomcat 的比较
    Tomcat设计模式
    Servlet 工作原理解析
    Tomcat 系统架构
    spring boot 打包方式 spring boot 整合mybaits REST services
    wireshark udp 序列号 User Datagram Protocol UDP
    Maven 的聚合(多模块)和 Parent 继承
    缓存策略 半自动化就是mybaitis只支持数据库查出的数据映射到pojo类上,而实体到数据库的映射需要自己编写sql语句实现,相较于hibernate这种完全自动化的框架我更喜欢mybatis
    Mybatis解决sql中like通配符模糊匹配 构造方法覆盖 mybits 增删改
  • 原文地址:https://www.cnblogs.com/ncscherb/p/5515972.html
Copyright © 2011-2022 走看看