`
clq9761
  • 浏览: 592813 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

Java语言高级应用

 
阅读更多

一、 Java反射
1.Java反射
是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs
   取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、
   superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,
   并可于运行时改变fields内容或唤起methods。


2.获取类的Class对象的几种方式:
  (1)类名.class。例:Boolean.class。
  (2)对象.getClass()。例:new Date().getClass();
  (3)Class.forName(“类名”);例:Class.forName("java.util.Date");


3.Constructor(获取类的构造方法)
  (1)得到某个类的所有构造方法。例:

Constructor  []constructors =  Class.forName("java.lang.String").getConstructors();

   (2)得到某个类的某一个构造方法。例:

Constructor constructor =  Class.forName("java.lang.String")
                  .getConstructo(StringBuffer.class);  

   (3)利用默认的构造方法创建Class对象所表示的类的新实例。例:       

 String str = (String)Class.forName("java.lang.String").newInstance();

 
4.Field(获取类的成员变量)
  (1)getField(""), 获取指定名称的公共成员变量。
  (2)getFields(),获取所有的公共成员变量。
  (3)getDeclaredField(“”),获取指定名称的声明变量,包含私有的。
  (4)getDeclaredFields(),获取所有的声明变量,包含私有的。
    示例代码如下:

 Order order = new Order(Long.parseLong("1001"),
    "订单1",
    Double.parseDouble("150.80"));
    order.setName("1001");
 // 获取成员变量Id,getField("")获取的成员变量必须是公共成员变量,否则抛异常。
 Field field = order.getClass().getField("id");
 // 获取成员变量name,getDeclaredField("")获取声明的所有成员变量,包含私有的。
 Field field2 = order.getClass().getDeclaredField("name");
 // 私有成员变量需采用暴力反射才能访问应用。
 field2.setAccessible(true);
 System.out.println(field2.get(order));

   注意:获取到的成员变量是类上面的,而不是对象上的,可通过成员变量.get(实例对象)获取到指定实例对象的成员变量值。

 

5.Method(获取类中的成员方法)
  (1)getMethod(String name, Class<?>... parameterTypes),获取指定方法名称和参数类型的公共成员方法。
  (2)getMethods(),获取所有的公共成员方法。
  (3)getDeclaredMethod(String name,Class<?>... parameterTypes),
       获取指定方法名称和参数类型的声明成员方法,包含私有成员方法在内。
   (4)getDeclaredMethods(),获取所有声明的成员方法,包含私有成员方法在内,但不包括继承的方法。
     示例代码如下:

Method  substring = Class.forName("java.lang.String")
      .getMethod("substring", int.class);
 String strAt = (String) substring.invoke(str, 3);
 // 获取私有的成员方法
 Method getHello = order.getClass().getDeclaredMethod("getHello");
 // 私有成员方法需暴力反射才能访问调用
 getHello.setAccessible(true);
 // 实例对象为null,表示该方法是static方法。
 System.out.println(getHello.invoke(null));

     
 6.其它说明
   (1)基本类型的一维数组可以被当做Object类型使用,不能当作Object[]类型使用,
        非基本类型的一维数组既可以被当做Object类型使用,又可以当作Object[]类型使用。
   (2)框架与工具类的区别在于,工具类被用户的类调用,而框架则是调用用户提供的类,
       由于在设计框架时无法知道用户提供的类,无法实例化具体的对象,需采用反射的方式来实现。

 

二、内省
1、内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。
    也就是说给定一个javabean对象,我们就可以得到/调用它的所有的get/set方法。
    例如类A中有属性name,那我们可以通过getName,setName来得到其值或者设置新的值。
    通过 getName/setName 来访问 name 属性,这就是默认的规则。
    Java 中提供了一套 API 用来访问某个属性的 getter/setter方法,
    通过这些API可以使你不需要了解这个规则,这些API存放于包java.beans中。         

 例:通过类 Introspector 来获取某个对象的 BeanInfo信息,然后通过 BeanInfo来
 获取属性的描述器(PropertyDescriptor),通过这个属性描述器就可以获取某个属性
 对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。

  

Order order = new Order();
order.setName( "ZX001" );
//如果不想把父类的属性也列出来的话,那getBeanInfo的第二个参数填写父类的信息
BeanInfo bi = Introspector.getBeanInfo(order.getClass(), Object.class);
PropertyDescriptor[] props = bi.getPropertyDescriptors();  
for(int i=0;i<props.length;i++){
   System.out.println(props[i].getName()+ "=" +
   props[i].getReadMethod().invoke(order, null ));
}

 2、Apache的commons包封装了很多对Java对象的基本操作,例如BeanUtils,PropertyUtils等,
可使用其对Java对象进行操作。

 

三、 注解

1、注解相当于一种标记,注解可以加在包,类,字段,方法,方法的参数以及局部变量上。
注解使得Java源代码中不但可以包含功能性的实现代码,还可以添加元数据。注解的功能类似于代码中的注释,
所不同的是注解不是提供代码功能的说明,而是实现程序功能的重要组成部分。
2、java1.5起默认的三个annotation类型:
 一个是@Override:只能用在方法之上的,用来告诉别人这一个方法是改写父类的。
 一个是@Deprecated:建议别人不要使用旧的API的时候用的,编译的时候会用产生警告信息,
     可以设定在程序里的所有的元素上.
 一个是@SuppressWarnings:这一个类型可以来暂时把一些警告信息消息关闭.

3、自定义注解类(@interface)

* RetentionPolicy.RUNTIME 内存中的字节码
 * RetentionPolicy.SOURCE Java源文件
 * RetentionPolicy.CLASS  Class文件
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface MyAnnotation {
	 // 注解属性(注解属性也可以是数组,枚举,注解等)
 String color() default "blue";
	 String value();
}

 @Retention用于描述注解的生命周期:
SOURCE代表的是这个Annotation类型的信息只会保留在程序源码里,源码如果经过了编译之后,
       Annotation的数据就会消失,并不会保留在编译好的.class文件里面。
ClASS的意思是这个Annotation类型的信息保留在程序源码里,同时也会保留在
   编译好的.class文件里面,系统默认值是CLASS.
RUNTIME,表示在源码、编译好的.class文件中保留信息,在执行的时候会把这一些信息加载到JVM中去的.

@Target用于描述注解的使用范围: 
TYPE(类型), FIELD(属性), METHOD(方法), PARAMETER(参数), CONSTRUCTOR(构造函数),
LOCAL_VARIABLE(局部变量), ANNOTATION_TYPE,PACKAGE(包),
其中的TYPE(类型)是指可以用在Class,Interface,Enum和Annotation类型上. 

4、注解类的反射调用,例:

@MyAnnotation(value = "test")
public class MyAnnotationTest {	
	public static void main(String []args){		
		// 判断是否加上MyAnnotation类型的注解		
		if(MyAnnotationTest.class.isAnnotationPresent(MyAnnotation.class)){
		MyAnnotation annation = MyAnnotationTest.class.getAnnotation(MyAnnotation.class);
		System.out.println(annation.color()+"#####"+annation.value());
		}
	}
}

 

四、 泛型

1.泛型(Generic type或者generics)是对Java语言的类型系统的一种扩展,以支持创建可以按类型
进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数
是运行时传递的值的占位符一样。
好处:泛型的主要目标是提高 Java 程序的类型安全。通过知道使用泛型定义的变量的类型限制,
编译器可以在一个高得多的程度上验证类型假设。将类型检查从运行时挪到编译时有助于您更容易找到错误,
并可提高程序的可靠性。
泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。


2.Java编译器编译生成的字节码会去掉泛型的类型信息,只要能通过编译器,就能往某个泛型集合中
  加入其它类型的数据。事例代码如下:

public static void main(String[] args)	throws Exception{		
	ArrayList<Integer> collection1=new ArrayList<Integer>();  
	collection1.add(1);  
	collection1.add(2);  
	collection1.add(3);  
	collection1.getClass().getMethod("add",				
			Object.class).invoke(collection1, "abcdefg");  
	System.out.println(collection1.get(3)); 
}

 

3.泛型相关术语:
ArrayList<E>,泛型类型。
ArrayList<E>中的E称为类型变量或类型参数。
ArrayList<Integer>称为参数化的类型。
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数。
ArrayList<Integer>中的<>称为typeof。
ArrayList称为原始类型。
参数化类型与原始类型可相互引用,但会出现警告。例:

Map<String,String> map = new HashMap();
Map map = new HashMap<String,String>();

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

Map<String,String> map= new HashMap<String,Object>();//编译器错误

 数组元素不能使用参数化的类型,可通过Array.newInstance(Classtype,int size)的方式来创建数组。

 

4.泛型通配符?
使用?通配符可以引用其它各种参数化的类型,?通配符定义的变量主要用作引用,可以调用与参数化无关的方法,
不能调用与参数化有关的方法。例:

public static void printCollection(Collection<?> cols){
	for(Object col:cols){
		System.out.println(col);
	}
	//cols.add("hello");// 编译错误,?通配符不能调用与参数化有关的方法
	cols.size();// ?通配符可以调用与参数化无关的方法			
	cols = new HashSet<Date>();// 引用通配符可以引用各种其它参数化的类型	
}

 (1) 限定通配符的上边界

// 正确
List<? extends Number> list= new ArrayList<Integer>();
// 错误
List<? extends Number> list2= new ArrayList<String>();

 (2)限定通配符的下边界

// 正确
List<? super Integer> list= new ArrayList<Number>();
// 错误
List<? super Integer> list2= new ArrayList<Byte>();

 

5、泛型方法
例:

static <E> void swap(E[] a,int i,int j){
	E t = a[i];
	a[i]= a[j];
	a[j] = t;
}

 

(1)用于放置泛型的类型参数的尖括号应出现在方法的其它所有修饰符之后和方法的返回类型之前,
       也就是紧邻返回值之前。类型参数通常用单个大写字母表示。
(2)只有引用类型才能作为泛型方法的实际参数,swap(new int[3],3,5)会报编译错误。
(3)泛型不仅在应用时可以使用extends限定符,在定义泛型时也可以使用extends限定符,
        并且可以用&来指定多个边界,如<E extends Serializable & Cloneable> void method(){}
(4)泛型也可以用类型变量来表示异常,称为参数化的异常,也可以用于方法的throws列表中,但不能用于catch子句中。
(5)在泛型中可以同时有多个类型参数,在定义它们的尖括号中用逗号分开,例:
 public static <K,V> V getValues(K key){}

 

6.类型参数的类型推断


  编译器判断泛型方法的实际参数的过程称为类型推断。根据调用泛型方法时实际传递的参数类型或返回类型来推断,具体规则如下:
(1)当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法时该处的实际应用
     类型来确定。例:swap(new String[3],3,4)->static<E> void swap(E[] a,int i,int j)
(2)当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时多处的实际应用类型都
    对应同一种类型,则根据实际应用类型来确定。例:add(3,5)->static<T> T add(T a,T b)
 (3)当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时多处的实际应用类型
    对应到了不同的类型,且没有返回值,这时取多个参数中的最大交集类型。例:下面语句对应的类型就是Number了。
    Fill(new Integer[3],3.5f)->static<T> void fill(T[] a,T v)
 (4)当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时多处的实际应用类型
    对应到了不同的类型,并且使用返回值,这时优先考虑返回值的类型,例如,下面语句实际对应的类型就是Integer了,
    编译器报告错误,将变量类型改为float,对比编译器的错误提示,再将变量类型改为Number。
(5)参数类型的类型推断具有传递性(a=c,b=c推出a=b),下面第一种情况推断实际参数类型为Object,
    编译没问题,而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型,编译将出现问题:
    copy(new Integer[5],new String[5])-->static <T> void copy(T[] a,T[] b)
    copy(new Vector<String>(),new Integer[5])-->static <T> void copy(Collection<T> a,T[] b)

 

7、泛型类型


(1)如果类的实例对象中的多处都要用到同一个泛型参数,这时采用泛型类型的方式进行定义,也就是类级别的泛型。
   以下示例为将方法级别的泛型改进为类级别的泛型:例:

public class GenericDao {	
	public <T> void  save(T po){}	
	public <T> T getById(String id){return null;}
}

 改进为:

public class GenericDao<T> {	
	public T field1;	
	public void  save(T po){}	
	public T getById(String id){return null;}
}

 

(2)类级别的泛型是根据引用该类名时指定的类型信息来参数化类型变量的,以下两种方式都可以: 

GenericDao<String> dao = null;
new GenericDao<String>();

 

(3)在对泛型类型进行参数化时,类型参数的实例必须是引用类型,不能是基本类型。当一个变量被声明为泛型时,
   只能被实例变量和方法调用,不能被静态变量和静态方法调用。

 

8、利用反射获得泛型的参数化类型
 

public class GenericReflection {	
private Vector<Date> dates = new Vector<Date>();
public void setDates(Vector<Date> dates) {
	this.dates = dates;
}	
public static void main(String args[]){		
	Method []methods = GenericReflection.class.getMethods();
	for(Method method:methods){
		if(method.getName().equals("setDates")){
			ParameterizedType paramType = (ParameterizedType) 
						method.getGenericParameterTypes()[0];
			// 获得参数类型
			System.out.println(((Class)paramType.getRawType()).getName());
			// 获得泛型的参数化类型
			System.out.println(((Class)paramType.getActualTypeArguments()[0]).getName());
		}
	}
}
}

 

分享到:
评论

相关推荐

    java高级应用教程

    本教程将带你深入理解Java语言的核心特性,并探讨如何在实际项目中有效地利用它们。 首先,让我们来看看Java的核心特性。Java是一种面向对象的语言,它的类、接口和继承机制构成了其核心。理解这些概念至关重要,...

    QTS青训-java8 高级应用与开发 实验答案

    【Java 8 高级应用与开发实验答案详解】 Java 8 是 Java 语言的一个重要版本,它引入了许多新特性,极大地提升了开发效率和代码质量。这个压缩包包含了一系列关于Java 8高级应用与开发的实验答案,涵盖了从集合框架...

    基于java的高级应用

    Java是一种广泛使用的编程语言,尤其在构建高级应用方面表现出色。本课程主要涵盖了基于Java的Web数据库访问技术、Web编程动态技术,包括JSP(Java Server Pages)和Servlet,以及高级数据库设计和基于MVC(Model-...

    java程序高级应用及开发

    Java程序的高级应用与开发是IT领域中一个深入且广泛的课题,它涵盖了Java技术的各个方面,包括语言特性、平台架构以及开发实践。让我们逐一探讨这些关键知识点。 首先,Java的诞生和发展规律是一个历史性的起点。...

    递归与迭代算法及其在JAVA语言中的应用.pdf

    在Java语言的高级应用中,如使用Spring框架进行企业级开发时,递归与迭代算法同样重要。例如,在处理嵌套的数据结构时,我们可能需要使用递归来遍历或是构建复杂的业务逻辑。在进行数据库操作时,迭代的思想也可以...

    Java语言程序设计(第2版)第1-6章 课后习题答案.pdf

    Java语言是由Sun Microsystems公司开发的一种高级语言,具有平台无关、对象oriented、安全性强等特点。 Java语言的特点 1. 平台无关:Java语言可以在任何支持Java虚拟机(JVM)的平台上运行,不受平台的限制。 2. ...

    java 高级语言编程 进阶版+中文

    它旨在深化读者对Java语言的理解,并介绍在企业级编程环境中经常用到的高级概念。由于Java生态丰富,这本书可能会通过案例和实战练习来帮助读者将理论知识应用到实际开发中。 此外,描述中提到的【部分内容】可能指...

    自考04747《Java语言程序设计》课后习题答案全集

    Java 语言是一种广泛应用于软件开发的高级编程语言,具有平台无关性、面向对象、分配内存自动管理等特点。本文将对 Java 语言的基础知识点进行总结,包括 Java 语言的特点、执行过程、开发和运行步骤、应用程序和小...

    高等教育自学考试_课程代码04747_Java语言程序设计(一).pdf

    "高等教育自学考试_Java语言程序设计" Java语言程序设计是一门基础课程,...本节课程对Java语言的基础知识进行了详细的介绍,帮助学生掌握Java语言的基本知识和技能, LayFoundation为进一步学习Java语言的高级知识。

    Java语言高级编程lesson1课件和期末试题参考答案

    本资源包"Java语言高级编程lesson1课件和期末试题参考答案"是针对Java学习者精心准备的材料,旨在帮助深入理解Java的高级概念,并为复习和考试提供指导。 首先,"lesson1.txt"文件很可能包含了Lesson1的学习内容,...

    Java语言实用教程

    - **Java语言的主要应用方向**:概述Java在不同领域的应用场景,如Web开发、移动应用开发(Android)、企业级应用等。 #### 二、Java开发环境搭建 - **JDK的获取和安装**:指导用户如何下载并安装Java开发工具包...

    Java语言程序设计教学论文.doc

    Java 语言作为一种面向对象的高级语言,具有安全性、多线程等特点,同时又具有独特的平台无关性的优势。为了适应社会的发展,培养更符合市场需求的计算机专业人才,很多高校都陆续开设了 Java 语言的相关课程。但是...

    Java编程 高级语言学习 基础应用 简单用法

    Java编程 高级语言学习 基础应用 简单用法

    Java中高级核心知识全面解析.pdf

    Java 中高级核心知识全面解析 ...Java 语言是一种功能强大且广泛应用的编程语言,本文对 Java 中的高级核心知识进行了全面解析,涵盖了基础知识到高级特性,旨在帮助读者更好地理解和掌握 Java 语言。

    Java语言程序设计

    根据给定的信息,“Java...综上所述,“Java语言程序设计”课程不仅涵盖了Java语言的基础知识,还涉及到了一些进阶技术和实战应用。通过学习这些内容,学生将能够全面掌握Java编程的核心技能,并能够应用于实际项目中。

    计算机软件开发中Java编程语言及应用方法的研究.pdf

    2)移动应用开发:Java语言可以用于开发Android移动应用程序,例如使用Java语言编写的Android应用程序。 3)桌面应用开发:Java语言可以用于开发桌面应用程序,例如使用Java语言编写的桌面应用程序。 知识点四:...

    编程语言java高级应用.pdf

    根据给定的文件信息,我们可以提炼出以下Java高级应用的知识点: 1. JDK API基础:JDK是Java Development Kit的缩写,包含了Java开发和运行所必需的工具和库。JDK API是Java类库的核心部分,它定义了Java语言和标准...

    计算机应用软件开发的Java编程语言分析.pdf

    Java 编程语言是一种高级编程语言,它是由 Sun Microsystems 公司(现在隶属 Oracle 公司)开发的。Java 语言的基本概念包括变量、数据类型、运算符、控制结构、函数等。 二、 Java 编程语言的语法结构 Java 语言...

Global site tag (gtag.js) - Google Analytics