Java基础加强一、二(Java5新特性和反射 补充)

本文深入探讨了Eclipse集成开发环境(IDE)的高级使用技巧,包括显示输入帮助、查看程序中变量、修改工程名字、透视图设置、代码模板、已有工程导入、Java版本配置、新特性介绍(静态导入、可变参数、增强的for循环、基本数据类型的自动拆箱与装箱、枚举、享元模式等)、反射应用、数组反射、ArrayList与HashSet的区别、类加载器、内省对JavaBean的操作等核心内容。


IDE:集成开发环境(integrated development environment)

设置在Eclipse中显示输入帮助:window—>Preferences—>General—>Keys:在(从上到下第二个文本框中:type filter text)输入content assist,就可以查看显示输入帮助的快捷键,也可以输入快捷键查看与之相关的服务,以免有不相同的服务用相同的快捷键。修改快捷键:修改下面的Binding选项即可

查看程序中变量的值:选中相关的语句,右击选debug as选项。运行后就切换到Debug透视图下,在代码中选中变量右击点watch选项后,在右上的窗口中即可查看。

修改工程的名字:选中工程点右键选Refactor—>Rename

透视图(perspective)即一系列小窗口的集合,也就是一些视图的集合。

 

设置workspace(工作台)的javac与java:

设置javac:window—>Preferences—>java—>complier,然后选择相应的版本

设置java:window—>Preferences—>java—>Installed JREs

而设置整个eclipse的java与javac则在window—>Preferences—>General中设置

高版本的java能运行低版本的javac编译的程序,反之低版本的java不能运行高版本javac编译的程序。

某个工程也已覆盖工作台的配置

 

设置代码模板:window—>Preferences—>java—>Templates,添加的话点new按钮。在Pattern中输入框架如:

try{

  ${line_selection}//代表被选中的代码,通过点Insert Variablea按钮添加

}finally{

  ${cursor}//代表光标

}

使用代码模板:选中相应的代码,点右键选Surround with添加。

 

在eclipse中添加已有的工程:首先将工程文件夹放到相应的workspace下,然后在该workspace下打开eclipse,点File—>import—>General—>Existing Projects into workspace—>select root directory

如果导入的工程所用的jdk与workspace中所用的jdk不同,就选中导入的工程点右键—>build path—>configure build path—>libraries,remove掉原有的JRE,在add新的JRE。如果jar包已经在工程中了,则选择Add JARs,若jar包没在工程中则增加外部的jar包:Add External JARs。我们此处选择Add libraries,增加JRE库。

 

(java5的新特性)

静态导入

import语句可以导入一个类或某个包中的所有类,所谓导入不占用任何的java资源,只是让我们写java原程序的时候少些一些前缀而已。

静态导入(java 1.5以后提供的)导入类中的静态方法,例如import static java.lang.Math.*,这样我们就可以直接使用:System.out.println(max(3,6));

 

overload: 重载,override:重写

 

可变参数(如:int a):用于一个方法可接受的参数个数不固定的情况。(jdk1.5提供)

特点:只能出现在参数列表的最后;符号“…”位于变量名之间,前后有无空格都可以;调用可变参数的方法时,编译器为该可变参数隐含创建一个数组,在方法中数以组的形式访问可变参数。例如:

public static int add(int x,int …args){

    int sum=x;

    for(int i=0;i<args.length;i++){

       sum+=args[i];

    }

    return sum;

}

 

增强的for循环:

语法:for(修饰符type 变量名:集合变量名){…},用变量去逐一取集合中的每一个元素的值,每取一个元素的值,就去执行一次循环体。

注意事项迭代变量必须在()中定义!集合变量可以是数组或实现了lterable接口的集合类。

举例,可将上面的代码修改为:

public static int add(int x,int ….args){

   int sum=x;

   for(int arg:args){

      sum+=arg;

   }

   return sum;

}

 

基本数据类型的自动拆箱与装箱

 

自动装箱:Integer num1=12;在java5以后允许这样表达,将整数12包装成一个Integer类对象,然后赋值给num1.

自动拆箱: System.out.println(num1+12);由于num1是Integer类型的对象,不能直接进行算术运算,所以此处会将num1拆箱,使之变成一个基本数据类型的数,然后参与运算。

 

基本数据类型的对象缓存:

Integer num1=12;

Integer num2=12;

Sytem.out.println(num1==num2);

此处的返回值为true。

Integer num3=129;

Integer num4=129;

Sytem.out.println(num3==num4);

此处的返回值为false。

因为对于基本数据类型的整数,如果要装箱成为Integer对象,并且如果这个数值在一个字节之内,即在-128-127之间的时候,把它们包装成Integer对象后,会回把它们缓存在一个池里面。带到下次用的时候就从池子里取,就不需要创建新的对象了,所以第一个返回值为true。较大的整数的使用没有小的整数那样频繁,所以就会产生不同的对象。

享元模式(flyweight)如果很多很小的对象有很多相同的东西,这样就可以编程一个对象,将其他不同的地方变成外部的属性,作为方法的参数传入。

 

Integer num5=Integer.valueOf(12); //这不是装箱,虽然也可以将12包装成Integer对象。

Integer num6=Integer.valueOf(12);

System.out.println(num5==num6);

返回结果的控制与上面相同。

 

枚举

使用枚举来规定某变量的值,也就是我们定义了一个新的类型并规定了它的值,以后使用该类型去定义变量时,变量的值就只能是那些已经规定好的值。而每一个枚举元素值都是一个实例对象。

(用抽象方法定义某些方法,就可以将大量的if else语句转移一个独立的实现了抽象方法的各个类中

 

枚举的定义及基本的使用:

public enum WeekDay{ 

//枚举也是一个类,此处WeekDay就是一个类,其中的每一个元素都是它的实例对象。

              SUN,MON,TUE,WED,THI,FRI,SAT;

    }

    WeekDay weekDay2 = WeekDay.FRI; //静态的

           System.out.println(weekDay2);

           System.out.println(weekDay2.name());

           System.out.println(weekDay2.ordinal());

      //返回FRI在WeekDay取值中是第几个,从0开始算,应返回5.还有一个getClass方法,因为枚举为一个类,它的值为对象,若调用getClass()方法,应返回WeekDay。 

           System.out.println(WeekDay.valueOf("SUN").toString());

// WeekDay.valueOf("SUN"):将SUN变为WeekDay的实例对象。

           System.out.println(WeekDay.values().length);

// WeekDay.values()返回一个WeekDay类型的数组,数组的值就是WeekDay所能取的值,也就是它的所有对象。便于进行遍历。

 

枚举中也可有构造方法:

public enum WeekDay{

 

              SUN(1),MON(),TUE,WED,THI,FRI,SAT;

/*元素列表为第一句,并且都是静态的,所以会自动调用相应的构造函数。只要用到该枚举其中的元素,构造方法就会被调用。元素后有大括号,并且其中有参数时,会调用有参的构造函数,否则会调用无参数的构造函数*/

              private WeekDay(){System.out.println("first");} //构造方法必须是私有的

              private WeekDay(int day){System.out.println("second");}

}

 

带有抽象方法的枚举

public enum TrafficLamp{

   RED,GREEN,YELLOW;

   public abstract TrafficLamp nextLamp();

}

因为这个枚举中有抽象方法,所以不能用new来产生新的对象。只能用其子类来产生RED,GREEN,YELLOW等对象。

public enum TrafficLamp{

              RED(30){

                     public  TrafficLamp nextLamp(){

                            return GREEN;

                     }

              },

        /*用匿名类产生子类的实例对象(注意:RED本身是对象,所以原理与

newTest(){}同),调用父类(此处为:TrafficLamp)的构造函数*/

              GREEN(45){

                     public  TrafficLamp nextLamp(){

                            return YELLOW;

                     }                  

              },

              YELLOW(5){

                     public  TrafficLamp nextLamp(){

                            return RED;

                     }                  

              };

              public abstract TrafficLamp nextLamp();

              private int time;

              private TrafficLamp(int time){this.time = time;}

       }

 

枚举只有一个成员时,就可以作为一种单例的实现方式。

 

 

Class类

java类用于描述一类事物的共性,该类事物拥有各种属性。至于这个属性的值是什么,则是有这个类的实例对象来确定的,不同的实例对象有不同的属性值。java程序中的各个java类,也属于同一类事物,也可用一个类来描述,这个类就是Class类。

由于java程序中的类在内存中以字节码的形式存在,所以Class类所对应的实例对象就是这些类相应的字节码,例如:有一个Person,它的字节码就是Class类的一个对象:

Class cls1= Person.class.另两种获得类的字节码的方式是,用类的实例对象调用getClass方法:Person p1=new Person(); p1. getClass()。或者用Class.forName(“相应类的完整名称(包括包名)”);调用Class.forName有两种情况,一个是相应的类没有加载到内存即java虚拟机中,则需要用类加载器将该类加载到内存中,然后获得相应的字节码;再一个是该类已经在加载到了java虚拟机中,则可直接返回其字节码。

像boolean、byte、char、short、int、long、float、double都分别有对应Class类的实例对象,有:Class cls=int.class;甚至void也是如此:Class cls=void.class。这九个类型是预定义的Class的实例对象。

凡在java程序中出现的类型都有各自的Class实例对象,都可以通过.calss来获得。

 

反射(注意:先获得类的字节码)

反射就是把java类中的各种成分映射成相应的java类。就是将一个类中各个成份转换成一个个类。例如,一个java类中用一个Class类的对象来表示,一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个的java类相应的对象来表示,就像汽车是一个类,汽车中的发动机,变速箱等也是一个个的类。表示java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,这些相应类是Field、Method、Contructor、Package等。获得这些类的实例对象后就获得了相应类的成分。

 

Constructor

Class类对应着java类的字节码,Constructor类则对应这着这些字节码中的一部分,它代表相应类类中的构造方法

得到某个类所有的构造方法,例如得到String类的构造方法:

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

//先得到该类的子节码

得到某一个构造方法:

Constructor constructor=

Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);

为了指明得到的是哪一个构造方法,需要将该构造方法的所有参数对应的字节码对象传递过来。

用反射的方法来实现:new String(new StringBufffer(“abc”))

Constructor constructor =String.class.getConstructor(StringBuffer.class);

//得到相应构造方法

String str=(String)constructor.newInstantce(new StringBuffer(“abc”));

//代码形式与new String(new StringBufffer(“abc”))进行比较

//得到对象,在编译时只知道调用构造方法,只有在运行时才知道调用的是哪一个

 

Class的newInstance方法:

用此方法可以比用Constructor更方便地使用无参数的构造方法来创建对象

例:String str=(String)Class.forName(“java.lang.String”).newInstance();

//该方法内部先得到默认的无参数的构造方法,然后用该构造方法创建对象

 

(在Eclipse中点右键选Source或点Alt+Shift+s,再选Generate Constructor using Fields,快速产生构造函数)

 

Filed类

Field代表类中的成员变量

public class ReflectPoint {

       private Date birthday = new Date();

      

       private int x;

       public int y;

    public ReflectPoint(int x, int y) {

              super();

              this.x = x;

              this.y = y;

}

 

import java.lang.reflect.Field;

public class ReflectTest {

       public static void main(String[] args) throws Exception {

       ReflectPoint pt1 = new ReflectPoint(3,5);

              Field fieldY = pt1.getClass().getField("y");//参数为变量名,指示获得哪个变量

              //fieldY的值是多少?是5,错!fieldY不是对象身上的变量,而是类上的,要用它去取某个对象上对应的值

              System.out.println(fieldY.get(pt1));//参数为对象

              Field fieldX = pt1.getClass().getDeclaredField("x");//获得私有的x

              fieldX.setAccessible(true);//获得了变量x,但不一定能访问,需要设置

              System.out.println(fieldX.get(pt1));

   }

}

 

例子:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的“b”改为“a”,主要代码如下;

private static void changeStringValue(Object obj) throws Exception {

              Field[] fields = obj.getClass().getFields();

              for(Field field : fields){

                     if(field.getType() == String.class){

        // getType():获得相应的类型,因为字节码是唯一的,所以此处用==进行比较

                            String oldValue = (String)field.get(obj);

                            String newValue = oldValue.replace('b', 'a');

                            field.set(obj, newValue);

                     }

              }

             

       }

 

Method类

Method类代表类中的成员方法

得到类中某一方法:以String类中的charAt为例,

Method methodCharAt = String.class.getMethod("charAt", int.class);

//第一个参数代表方法名,第二参数(及以后)为该方法的参数的字节码

System.out.println(methodCharAt.invoke(str1, 1));

/* invoke表示调用methodCharAt所代表的方法,methodCharAt所代表的方法是类上的,与对象无关,所以需要第一个参数指明该方法作用于的对象。第二个参数代表methodCharAt所代表的方法所用的参数。如果传递给invoke的第一参数为null,则表示该Method对象对应的是一个静态方法*/

若用1.4的jdk则上语句变为:

System.out.println(methodCharAt.invoke(str1, new Object[]{1}));

 

用反射的方法执行某个类中的main方法

目标:写一个程序,这个程序能够根据用户提供的类名,执行给类中的main方法。

普通方式:

class A{

    public static void main(String[] args){

         B.main(new String[]{"111","222","333"});

    }

}

class B{

    public static void main(String[] args){

      }

}

但若事先不知道要启动的类的名字,要根据参数去启动某个类的main方法时:

String startingClassName = args[0];

//获得要启动的类的名字,但程序只知道它是String的一个值,不知道它代表一个类

Method mainMethod=Class.forName(startingClassName).getMethod("main", String[].class);

//mainMethod.invoke(null, new String[]{"111","222","333"});

//按照上语句运行,会有错误,因为运行时程序会把第二参数拆包,就成了三个参数而main方法只接受一个参数,所以只能用下面这两种形式

              //mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});

 

              mainMethod.invoke(null, (Object)new String[]{"111","222","333"});

 

数组的反射

只要是同一种类型和相同的维度的数组,都可以反射成相同的一段字节码,即同一个Class类,java提供了数组的反射类:Array

例如:1、

int [] a1 = new int[]{1,2,3};

int [] a2 = new int[4];

int[][] a3 = new int[2][3];

String [] a4 = new String[]{"a","b","c"};

System.out.println(a1.getClass() == a2.getClass());//返回true

System.out.println(a1.getClass() == a4.getClass());//返回false

System.out.println(a1.getClass().getSuperclass().getName());

// getSuperclass()获得父类

2、

Object aObj1 = a1;

Object[] aObj4 = a3;

//因为a3是二维数组,编译程序会将每一个第二维的数组作为一个Object,这样产生的Object数组的每一个元素是一个数组。

Object[] aObj5 = a4;//编译程序会将每一个String当做Object,所以编译通过。

而:Object[] aObj3 = a1;编译就无法通过,因为基本数据类型编译程序不会将其当做Object。所以:

System.out.println(Arrays.asList(a4));//可以将数组成分打印出来:[a,b,c]

而System.out.println(Arrays.asList(a1));//不能正常打印

3、

private static void printObject(Object obj) {

//为了打印传来的对象,需要判断是不是数组,是的话需要将所有的数组元素打印出来

              Class clazz = obj.getClass();

              if(clazz.isArray()){

                     int len = Array.getLength(obj);

                     for(int i=0;i<len;i++){

                            System.out.println(Array.get(obj, i));

                     }

              }else{

                     System.out.println(obj);

              }

             

       }

 

 

ArrayList和HashSet比较及HashCode分析

ArrayList是一个实现了Collection接口的类,Collection的各对象元素之间没有指定的顺序,允许有重复元素和多个null元素对象,即不满足排序,List各对象元素之间有顺序,允许有重复元素和多个null元素对象,ArrayList就是一个实现了List接口的类,所以在ArrayList存放的对象的引用是有位置顺序的,并且可以放多个指向同一个对象的引用。而HashSet则不能放多个指向同一个对象的引用

如果一个类产生的对象用哈希算法存储,那么该类必须覆盖Object.hashCodde方法(其返回值为散列码)和Object.equals方法。

因为即使两个值对象内容完全相同,它们从Object类所继承到的hashCodde中得到的返回值是不同的,因此我们若想让两个内容相同的值对象的hashCode方法的返回值相同,就必须覆盖从Object类所继承到的hashCodde方法。

如果根据 equals(Object) 方法的结果,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都也必须生成相同的整数结果。

如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法 要求一定生成不同的整数结果。

当一个对象被存储进HashSet集合后,就不能修改这个对象中的那些参与计算哈希值的字段了,否则,对象修改后的哈希值与最初存储进HashSet集合中的哈希值就不同了,在这种情况下,以该对象的当前引用作为参数去HashSet集合中去检索对象,就返回不到该对象的结果,也无法从HashSet中删除该对象,从而造成内存泄露。

 

反射的作用就是实现框架功能(如前面的调用类的main方法,可以处理任何类(及以后的任何类)的main方法,进行调用)

框架可以调用用户提供的类,实现其功能,而工具类则是被用户调用的,在写框架的时候无法知道要调用的类名,也就无法直接new某个实例对象,所以要用到反射。

对于用户而会有一个配置文件(扩展名为:properties)内容一般为要启动的类名,输入的格式为等式的格式:例如:className=java.util.ArrayList

小框架举例,调用ArrayList,配置文件的内容如上例,

InputStream ips = new FileInputStream("config.properties");//读取文件

Properties props = new Properties();//获取其中的属性值

/* Properties与HashMap的功能差不多,只是Properties能自动添加键值对,它能将自己的键值对在初始化时从硬盘加载到内存,也可以将键值对从内存放到硬盘*/

props.load(ips);

ips.close();

//关闭与ips相关的资源而不是关闭该对象,关闭该对象是java垃圾处理器的事

String className = props.getProperty("className");

Collection collections = (Collection)Class.forName(className).newInstance();

//产生相应的集合对象

 

类加载器

类可以加载.class文件进内存,自然也可以加载其他的文件,所以除了用InputStream ips = new FileInputStream("config.properties");这种方法外也可以用类加载器进行加载:,但使用类加载器这种方法只能读取,而不能写。例如

ReflectTest2.class.getClassLoader().getResourceAsStream("name");

//先调用类(此处为ReflectTest2)反过来获得加载他进来的类加载器,用getClassLoader()方法

// getResourceAsStream(name);该方法会在classpath目录下逐个查找要加载的文件

 

InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");

//尽管是根目录,参数中的cn前面也无斜杠

Class类中提供了在不调用getClassLoader()方法的情况下,加载文件的方法

InputStream ips = ReflectTest2.class.getResourceAsStream("resources/config.properties");

//此处为相对目录

InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");

//此处为根目录

 

内省

内省用于对javabean的操作,它对应的英文单词为:IntroSpector

(javabean中应有一个无参数的构造函数)

javabean是一个特殊的java类,这个类中的方法的名称符合约定的规则,例如,有getXxx和setXxx方法,javabean的属性名称,是通过其get和set方法得知的,而不能直接通过其属性得知(javabean的属性为private的)。在javabean中,去掉get或set方法中的get或set后就可以得到其属性名,但其字母的大小写是有规定的,去掉get或set后,若第二个字母是小写的,则第一个字母也应小写;若都是大写的(不包括仅一个字母的情况,一个字母时为小写),则不变。

我们可以像对普通类一样对javabean进行编程和反射操作。而对于一般的类若它有getXxx和setXxx方法(有其中之一也可),则可以将其看成javabean,对它进行与javabean相同的有关操作,当然可以像一般类那样进行操作。

如果要在两个模块之间传递多个信息,可以将这些信息封装到一个javabean中,这种JavaBean的实例对象称为值对象(Value Object,简称VO)。

JDK中提供了对JavaBean进行操作的API,这些API就称为内省。

应用举例;

import java.beans.IntrospectionException;

import java.beans.Introspector;

import java.lang.reflect.Method;

public class IntroSpectorTest {

       public static void main(String[] args) throws Exception {

       ReflectPoint pt1 = new ReflectPoint(3,5);

       //此为被当做JavaBean的类,其有private类型的属性:x

        String propertyName = "x";

      Object retVal = getProperty(pt1, propertyName);

        System.out.println(retVal);

        Object value = 7;

        setProperties(pt1, propertyName, value);

  }

  private static void setProperties(Object pt1, String propertyName,

                   Object value) throws IntrospectionException,

                   IllegalAccessException, InvocationTargetException {

            PropertyDescriptor pd2 = new PropertyDescriptor(propertyName,pt1.getClass());

// PropertyDescriptor属于java.beans下的类,用于描述类的属性,注意参数

            Method methodSetX = pd2.getWriteMethod();

//对于类的属性有读和写两种操作,get对应于读,而set对应于写。

            methodSetX.invoke(pt1,value);

     }

 

     private static Object getProperty(Object pt1, String propertyName)

                   throws IntrospectionException, IllegalAccessException,

                   InvocationTargetException {

         PropertyDescriptor pd = new PropertyDescriptor(propertyName,pt1.getClass());

            Method methodGetX = pd.getReadMethod();

            Object retVal = methodGetX.invoke(pt1);

       return retVal;

       }

(在Eclipse中抽取一个方法:选中要放进方法中的代码,点右键选Refactor—>Extract Method)

另一种设置和读取属性的方法较为复杂,采用遍历BeanInfo的所有属性方式来查找和设置某个类的对象的属性。调用IntroSpector.getBeanInfo方法,得到的BeanInfo对象封装了把这个类当做JavaBean看的结果信息。

将上方法体中的代码可修改为:

BeanInfo beanInfo =  Introspector.getBeanInfo(pt1.getClass());

            PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();

       //获得了相应类的所有属性

            Object retVal = null;

            for(PropertyDescriptor pd : pds){

                   if(pd.getName().equals(propertyName))

                   {

                          Method methodGetX = pd.getReadMethod();

                          retVal = methodGetX.invoke(pt1);

                          break;

                   }

            }

            return retVal;

 

使用Beanutils工具包设置和读取javabean的属性(均为静态方法)

使用该工具包还要添加包:commons-logging-1.1.jar

1、

ReflectPoint pt1 = new ReflectPoint(3,5);

BeanUtils.setProperty(pt1, "x", "9");

//第三个参数表示被设置的属性的值,注意类型为String

System.out.println(BeanUtils.getProperty(pt1, "x").getClass().getName());

//得到的属性值的类型也为String,而不是原类型,采用String类型便于数据的传输

若采用PropertyUtils类,则采用原属性

PropertyUtils.setProperty(pt1, "x", 9);

System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName());

2、

Beanutils工具包支持属性链

即某一个类的某个属性的类型为类类型,并且该类类型所对应的类也可以当做javabean,那么可以通过BeanUtils,设置该属性的属性

BeanUtils.setProperty(pt1, "birthday.time", "111");

//birthday类型为Data,此处设置birthday的属性time

System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));

 

拷贝对象的属性:copyProperties(java.lang.Object dest, java.lang.Object orig)

把javabean转换成map:describe(java.lang.Object bean)返回map

反之将map转为javabean:

void populate(java.lang.Object bean,java.util.map properties)

同样,BeanUtils可以设置map的值:

 

---------------------- <a href="http://edu.csdn.net/heima" target="blank">android培训</a>、<a href="http://edu.csdn.net/heima" target="blank">java培训</a>、期待与您交流! ----------------------

详细请查看:<a href="http://edu.csdn.net/heima" target="blank">http://edu.csdn.net/heima</a>

该资源包含源代码 易看易懂 其实就是发射机制 反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测修改它本身状态或行为的种能力。这概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp面向对象方面取得了成绩。其中LEAD/LEAD++ 、OpenC++ 、MetaXaOpenJava等就是基于反射机制的语言。最近,反射机制也被应用到了视窗系统、操作系统文件系统中。 反射本身并个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指类应用,它们能够自描述自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)监测(examination),并能根据自身行为的状态结果,调整或修改应用所描述行为的状态相关的语义。可以看出,同般的反射概念相比,计算机科学领域的反射单单指反射本身,还包括对反射结果所采取的措施。所有采用反射机制的系统(即反射系统)都希望使系统的实现更开放。可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并定采用了反射机制,开放性是反射系统的必要条件。般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实际状态行为上的情况,反之亦然。开放性原因连接是反射系统的两大基本要素。13700863760 Java中,反射种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用当,反射的成本很高。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值