——Java高级应用

喜欢而已 提交于 2020-01-09 00:16:31

一、类加载

  类加载是指将类的class文件读入内存,并为之创建一个java.lang.Class对象。系统可以在第一次使用某个类时加载该类,也可以采用预加载机制来加载某个类。

  1、Class类

    java.lang.Class类封装了一个对象和接口运行时的状态,当加载类时Class类型的对象将自动创建。Class类没有公共构造方法,其对象是JVM在加载类时通过调用

  类加载器中的defineClass()方法自动构造,因此不能显示地实例化一个Class对象。

    Class类的常用方法(记得填坑)

    每个类被加载之后,系统都会为该类生成一个对应的Class对象,通过Class对象就可以访问到JVM中该类的信息。一旦类被载入JVM中,同一个类将不会被再次载入,

  被载入JVM的类都有一个唯一表示,该表示是该类的全限定类名。

    在Java程序中获取Class对象有如下三种方式:

1     //1、使用Class.forName()方法
2     Class strClass = Class.forName("java.lang.String");
3     //2、使用类的class属性
4     Class<Float> fclass = Float.class;
5     //3、使用实例对象的getClass()方法
6     Date nowTime = new Date();
7     Class dateClass = nowTime.getClass();

  2、类加载步骤

    类的加载有三个步骤:加载、连接、初始化。

    类的加载是由类加载器完成,类加载器由JVM提供;除此之外,开发者可以通过继承ClassLoader类来创建自己的类加载器。通过使用不同的类加载器,可以从

  不同来源加载类的二进制数据。

    类的连接是指将类的二进制数据合并到JRE中。

    类的初始化是指对类变量进行初始化。有以下几个步骤:

    (1)如果类没有被加载和连接,则程序先加载并连接该类

    (2)如果类的直接父类未被初始化,则先初始化其直接父类

    (3)如果类中有初始化语句,则系统直接执行初始化语句

    因此,当程序使用任何一个类时,JVM会保证该类及其所有祖先类都会被初始化。

  3、类加载器

    类加载器负责将磁盘或网络上的.class文件加载到内存中,并为之生成对应的java.lang.Class对象。

  4、ClassLoader类

    java.lang.ClassLoader是一个抽象类,通过继承ClassLoader类来实现自定义的用户类加载器,以扩展JVM动态加载类的方式。

   ClassLoader类中包含了大量的protected方法,都可以在子类中被重写。(有待理解完善)

二、反射

  在程序运行时获取对象的真实信息有以下两种做法:

    **在知道对象的具体类型的情况下,可以先使用instanceof 运算符进行判断,再利用类型强制转换将其转换成运行时的类型变量

    **在无法预知该对象属于哪些类的情况下,必须通过反射来发现该对象和类的真实信息

  反射机制允许程序在运行时借助Reflection API取得任何类的内部信息,并能直接操作对象的内部属性及方法。

  Java反射机制主要提供了以下功能:

    *在运行时判断任意一个对象所属的类

    *在运行时构造任意一个类的对象

    *在运行时获取任意一个类所具有的成员变量和方法

    *在运行时调用任意一个对象的方法

    *生成动态代理

  1、Executable抽象类

    该抽象类代表可执行的类成员。Executable抽象类派生了Constructor和Method两个子类。Executable抽象类提供了大量方法来获取参数、

   修饰符或注解等信息。

  2、Constructor类

    Constructor类用于表示类的构造方法,通过调用Class对象的getConstructors( )方法可以获取当前类的构造方法的集合。

  3、Method类

    Method类用于封装方法的信息,调用Class对象的getMethods( )或getMethod( )可以获取当前类的所有方法或指定方法。

  4、Field类

    Field类用于封装属性的信息,调用Class对象的getField( )或getFields( )方法可以获取当前类的所有属性或指定属性。

  5、Parameter类

    Parameter类也是Java 8 新增的API,每个Parameter对象代表方法的一个参数。

三、枚举

  在开发过程中,经常遇到一个类的实例对象是有限而且固定的情况。

  定义枚举类使用enum关键字。枚举类是一种特殊的类,与普通类有如下区别:

    **枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是继承Object类,因此枚举类不能显式继承其他父类。

    **使用enum定义非抽象的枚举类时默认会使用final修饰,因此枚举类不能派生子类。

    **枚举类的构造方法只能使用private访问修饰符

    **枚举类的所有实例必须在枚举类的类体第一行显式列出,否则该枚举类永远不能产生实例。列出的枚举实例默认使用public static final进行修饰。

  1、定义枚举类

    语法格式:

      [ 修饰符 ]  enum  枚举类名{

        //第一行列举枚举实例

      }

    枚举一旦被定义,就可以直接使用该类型的枚举实例。所有枚举类型都会包括两个预定义方法:values( ) 和 valuesOf( )

方法 功能描述
public static enumtype []values()  返回一个枚举类型的数组,包含该枚举类的所有实例值
public static enumtype valueOf(String str) 返回指定名称的枚举实例值

    语法:枚举类.实例

  2、包含属性和方法的枚举类

    枚举类也是一种类,具有与其他类几乎相同的特性,因此可以定义枚举的属性、方法以及构造方法。但是,枚举类的构造方法只是在构造枚举实例值时

  被调用。每一个枚举实例值都是枚举类的一个对象,因此创建每个枚举实例时都需要调用该构造方法。

 1 public enum Season {
 2     //第一行列出4个枚举实例:春夏秋冬
 3     SPRING("春"),SUMMER("夏"),FALL("秋"),WINTER("冬");
 4     //定义一个属性
 5     private String name;
 6     //构造方法
 7     Season(String name){
 8         this.name = name;
 9     }
10     //方法
11     public String toString(){
12         return this.name;
13     }
14     
15 }

  3、Enum类

  所有枚举类都继承自java.lang.Enum,该类定义了枚举类公用的方法。这个类实现了java.lang.Serializable和java.lang.Comparable两个接口

四、注解

  注解Annotation是告知编译器要做什么事情的说明,在程序中可以对任何元素进行注解,包括:Java包、类、构造方法、域、方法、参数、属性等。

  APT注解处理工具负责提取注解中包含的元数据,并会根据这些元数据增加额外功能。

  注解中元数据的作用:编写文档、代码分析、编译检查

  1、基本注解

    @Override:用于限定重写父类的方法,使用该注解修饰的方法必须重写父类中的方法,否则会发生编译错误

    @Deprecated:用于标示某个元素已过时,当程序使用已过时的类、方法等,编译器会给出警告

    @SuppressWarnings:用于抑制编译警告的发布,允许开发人员取消显式指定的编译器警告;

    @SafeVarargs:在Java 7中新增,用于抑制“堆污染”警告

    @FunctionalInterface:在Java 8中新增,用于指定某个接口必须是函数式接口

  2、定义注解

    语法格式:

      [ 修饰符 ]  @interface  注解名{

        。。。

      }

    自定义注解是通过@interface声明,注解的成员由未实现的方法组成,方法只有声明没有方法体,注解中的成员将在使用时进行实现

    在定义注解时,可以使用default语句为注解成员指定默认值。语法:类型成员( ) default 值;

1 @Retention(RetentionPolicy.RUNTIME)
2 public @interface MyAnno {
3     String comment();
4     int order();
5 }

 

  3、使用注解

    注解大多是为其他工具提供运行信息或决策依据而设计的,任何Java程序都可以通过使用反射机制来查询实例的信息。

    在java.lang.reflect中有一个AnnotatedElement接口,用于在反射过程中获取注解信息,并为注解相关操作提供支持。

方法 功能描述
Annotation getAnnotation(Class annotype) 返回调用对象的注解
Annotation getAnnotations() 返回调用对象的所有注解
Annotation getDeclareedAnnotations() 返回调用对象的所有非继承注解
Boolean isAnnotationPresent(Class annotype) 判断与调用对象关联的注解是由annotype指定的

  

 1 //使用自定义的@MyAnno注解修饰类
 2 @MyAnno(comment = "类注解", order = 1)
 3 class MyClass{
 4     //使用自定义的@MyAnno注解修饰方法
 5     @MyAnno(comment = "方法注解", order = 2)
 6     public void method(){
 7 
 8     }
 9 }
10 public class AnnoDemo {
11     public static void main(String[] args) throws Exception {
12         //获取MyClass类注解
13         MyAnno anno = MyClass.class.getAnnotation(MyAnno.class);
14         //输出类注解信息
15         System.out.println(anno.comment()+"序号:"+anno.order());
16         //获取MyClass类的method方法
17         Method mth = MyClass.class.getMethod("method");
18         //获取该方法的注解
19         MyAnno anno1 = mth.getAnnotation(MyAnno.class);
20         //输出
21         System.out.println(anno1.comment()+"序号:"+anno1.order());
22     }
23 }

  4、元注解

    元注解的作用就是负责注解其他注解。

    @Retention:指定其所修饰的注解的保留周期

    @Document:该注解是一个标记注解,用于指示一个注解将被文档化

    @Target:用来限制注解的使用范围

    @Inherited:该注解使父类的注解能被子类继承

    @Repeatable:该注解是Java 8新增的注解,用于开发重复注解

    类型注解(Type Annotation):该注解是Java 8 新增的注解,可以用在任何用到类型的地方。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!