java强化篇(四)---注解、泛型。类加载器.线程

Java的三个基本注解

@Deprecated :标记此程序元素已过时,通常是因为它很危险或存在更好的选择。

@SuppressWarnings :取消显示指定的编译器警告。

@Override :表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。

元注解@Retention--定义注解类的存在区域,有三种取值:RetentionPolicy.SOURCE、RetentionPolicy.CLASS、 RetentionPolicy.RUNTIME,分别对应java源文件、class文件、内存中的字节码。

元注解@Target:确定注解类可用范围,取值ElementType.METHOD...

定义基本类型的属性

在注解类中增加String color();

引用:@MyAnnotation(color=“red”)

用反射获得注解对应的实例对象后,再通过对象调用属性对应的方法。

MyAnnotation a=(MyAnnotation)AnnotationTest.class.getAnnotation(MyAnnotation)

System.out.println(a.color);

为属性定义缺省值String color()default “red”;

Value属性  String value();

如果一个 注解只有一个名称为value的属性,且你只想设置value的属性,可以省略,@MyAnnotation(“red”);

泛型

ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:

1、 整个ArrayList<E>称为泛型类型

2、ArrayList<E>中E称为类型变量或类型参数

3、整个ArrayList<Integer>称为参数化的类型

4、ArrayList<Integer>中的Integer叫类型参数的实例或实际类型参数

5、ArrayList<Integer>中的<>念typeof

6、ArrayList称为原始类型

参数化类型与原始类型的兼容性-编译警告

Collection<String> = new Vector();

Collection = new Vector<String >();

参数化类型不考虑类型参数的继承关系

Vector<String> v = new Vector<Object>(); //错!

Vector<Object> v = new Vector<String>();//错!

在创建数组实例时,数组的元素不能使用参数化的类型。

定义泛型类

类中的多个方法要使用同一个泛型参数,此时要定义类级别的泛型。

public class GenericDao<T>{

private T field1;

public void save<T obj>{}

public T getById(int ID){}

}

类级别的泛型是根据引用类名指定的泛型信息来参数化变量的.

GenericDao<String> dao=null;

new GenericDao<String>();

注意

1、在对泛型参数化时,必须是引用类型,不能是基本类型。

2、当一个类被声明为泛型时,只能被实例变量和方法调用(还有内嵌类),而不能被静态变量和静态方法调用。因为类静态成员是被所有参数化的类所共享的,所以静态成员不应该拥有类级别的类型参数。

通过反射获得泛型的参数化类型

Vector<Date> v = newVector<Date>();

通过v.getClass()是无法获得泛型的参数化类型的。

将其传递给一个方法,可实现此功能。

public static void applyVector(Vector<Date> v){}

Method applyMethod =GenericTest.class.getMethod("applyVector",        Vector.class);

Type[] types = applyMethod.getGenericParameterTypes();

ParameterizedType pType = (ParameterizedType)types[0];

System.out.println(pType.getRawType());//Vector

System.out.println(pType.getActualTypeArguments()[0]);//Date

类加载器之间的父子关系和管辖范围图

当java虚拟机加载类时,到底用哪个类加载器?

◇首先当前线程的类加载器去加载线程中的第一个类

◇如果类A引用了类B,那么java虚拟机将使用加载类A的类加载器去加载类B

◇还可以直接调用ClassLoader.loaderClass()方法来指定某个类加载器去加载

每个类加载器加载时,又委托给其上级的类加载器。

当所有祖宗类加载器没有加载到该类,则回到发起者类加载器,还加载不到,则抛出ClassNoFoundException,不是再找发起者类加载器和儿子,因为没有getChild方法。——从上到下的加载。

自定义类加载器

工作机制

父类——>loadClass/findClass()/得到class文件的内容转换成字节码—>difineClass()/将一个 byte 数组转换为 Class 类的实例

实现步骤

◇自定义的类加载器必须继承ClassLoader

◇覆盖findClass方法

◇覆盖difineClass()方法

传统线程机制的回顾

创建线程的两种传统方式

在Thread子类覆盖的run方法中编写运行代码

涉及一个以往知识点:能否在run方法声明上抛出InterruptedException异常,以便省略run方法内部对Thread.sleep()语句的try…catch处理?

在传递给Thread对象的Runnable对象的run方法中编写代码

总结:查看Thread类的run()方法的源代码,可以看到其实这两种方式都是在调用Thread对象的run方法,如果Thread类的run方法没有被覆盖,并且为该Thread对象设置了一个Runnable对象,该run方法会调用Runnable对象的run方法。

问题:如果在Thread子类覆盖的run方法中编写了运行代码,也为Thread子类对象传递了一个Runnable对象,那么,线程运行时的执行代码是子类的run方法的代码?还是Runnable对象的run方法的代码?

涉及到的一个以往知识点:匿名内部类对象的构造方法如何调用父类的非默认构造方法。

定时器的应用

Timer类

TimerTask类

多个线程访问共享对象和数据的方式

如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做。

如果每个线程执行的代码不同,这时候需要用不同的Runnable对象,有如下两种方式来实现这些Runnable对象之间的数据共享:

将共享数据封装在另外一个对象中,然后将这个对象逐一传递给各个Runnable对象。每个线程对共享数据的操作方法也分配到那个对象身上去完成,这样容易实现针对该数据进行的各个操作的互斥和通信。

将这些Runnable对象作为某一个类中的内部类,共享数据作为这个外部类中的成员变量,每个线程对共享数据的操作方法也分配给外部类,以便实现对共享数据进行的各个操作的互斥和通信,作为内部类的各个Runnable对象调用外部类的这些方法。

上面两种方式的组合:将共享数据封装在另外一个对象中,每个线程对共享数据的操作方法也分配到那个对象身上去完成,对象作为这个外部类中的成员变量或方法中的局部变量,每个线程的Runnable对象作为外部类中的成员内部类或局部内部类。

总之,要同步互斥的几段代码最好是分别放在几个独立的方法中,这些方法再放在同一个类中,这样比较容易实现它们之间的同步互斥和通信。

极端且简单的方式,即在任意一个类中定义一个static的变量,这将被所有线程共享。

时间: 2024-08-01 16:33:04

java强化篇(四)---注解、泛型。类加载器.线程的相关文章

java之 ------ JUnit、注解、类加载器

JUnit软件测试技术(工具) 在项目中建立专门用户测试的包结构. 在Junit中,通过@Test注解,可以运行一个方法(鼠标放在选择要运行的方法名上,单击右键,选择Run As,再选择JUnit Test即可). 这样做的好处就是不用在主代码中添加测试代码,避免了代码的冗余.而且一个测试类,可以测试多项功能,不需要main方法. 一. Junit注解说明 使用了@Test注解应该满足以下条件: 1) 必须是无参数的非静态方法. 2) 添加@Test注解的类,必须拥有一个无参数的公开构造 pac

高新技术---内省、注解、类加载器

第一讲     内省引出JavaBean 一.内省 1.内省对应的英文单词为IntroSpector,英文意思是检查.视察.体检之意,对于程序即对内部进行检查,了解更多的底层细节. 2.内省的作用:主要针对JavaBean进行操作. 二.JavaBean 1.简述: 1)JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法符合某种特殊的命名规则. 2)它是一种特殊的Java类,其中的方法符合特殊的规则.只要一个类中含有get或is和s

Java虚拟机笔记 – JVM 自定义的类加载器的实现和使用2

1.用户自定义的类加载器: 要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用. findClass protected Class<?> findClass(String name) throws ClassNotFoundException 使用指定的二进制名称查找类.此方法应该被类加载器的实现重写,该实现按照委托模型来加载类.在通过父

java提高篇(四)_理解java的三大特性之多态 转自 http://cmsblogs.com

多态就是指程序中定义 的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该 引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定.因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让 引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个 运行状态,这就是多态性 一. 向上转型

Java虚拟机笔记 – JVM 自定义的类加载器的实现和使用

1.用户自定义的类加载器: 要创建用户自己的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的findClass(String name)方法即可,该方法根据参数指定类的名字,返回对应的Class对象的引用. findClass protected Class<?> findClass(String name) throws ClassNotFoundException 使用指定的二进制名称查找类.此方法应该被类加载器的实现重写,该实现按照委托模型来加载类.在通过父

Java基础加强-(注解,类加载器,servlet3.0新特性)

1.   Annotation注解 1.1.  Annotation概述 Annotation是JDK 5.0以后提供对元数据的支持,可以在编译.加载和运行时被读取,并执行相应的处理.所谓Annotation就是提供了一种为程序元素设置元数据的方法,可用于修饰包.类.构造器.方法.成员变量.参数和局部变量的声明,这些信息被存储在Annotation的“name=value”对中. Annotation能被用来为程序元素(类.方法.成员变量等)设置元数据,比如一段代码的作者或者告诉编译器禁止一些特

第17天(基础加强_注解_类加载器_动态代理)_学习目标版本

学习目标 能够使用Junit进行单元测试 能够说出注解的作用 能够使用JDK提供的3个注解 能够根据基本语法编写自定义注解实现类 能够了解自定义注解解析 能够了解元注解使用 能够根据上课案例分析,编写模拟@Test案例 能够理解动态代理原理 能够使用动态代理Proxy编写代理类 Junit单元测试 Junit介绍 JUnit是一个Java语言的单元测试框架,简单理解为可以用于取代java的main方法.Junit属于第三方工具,一般情况下需要导入jar包,不过,多数Java开发环境已经集成了JU

Java---JUnita、注解与类加载器详解以及实例

JUnit软件测试技术(工具) 在项目中建立专门用户测试的包结构. 在Junit中,通过@Test注解,可以运行一个方法. ★ Junit注解说明 使用了@Test注解应该满足以下条件: 1) 必须是无参数的非静态方法. 2) 添加@Test注解的类,必须拥有一个无参数的公开构造 ★ JUnit测试示例演示 1.运行完成后,可以在Junit的窗口上看到运行所用的时间和结果信息. 2.被测试程序的运行结果出现在控制台(Console)上. "项目"代码: package cn.hncu.

java JVM-自定加密和解密类加载器

简单加密解密(取反)操作int a=3; //00000011//^异或操作,相同为1,0xff,表示一个十六进制数,表示a和1111 1111 进行异或操作,结果为1111 1100System.out.println(Integer.toBinaryString(a^0xff)); //对二进制取反,转换成二进制字符串//ff表示1111 1111,f=15 public class Lockloader { public static void main(String[] args) {