首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

JAVA 构造器,extends[承继],implements[实现],Interface[接口],reflect[反射],clone[克隆],final,s

2012-08-26 
JAVA构造器,extends[继承],implements[实现],Interface[接口],reflect[反射],clone[克隆],final,static,ab

JAVA 构造器,extends[继承],implements[实现],Interface[接口],reflect[反射],clone[克隆],final,static,abstract[抽象]


构造器[构造函数]:

在java中如果用户编写类的时候没有提供构造函数,那么编译器会自动提供一个默认构造函数.它会把所有的实例字段设置为默认值:所有的数字变量初始化为0;所有的布尔变量设置为false;所有对象变量设置为null;

PS:

只有在类中没有其它构造器的时候,系统才会提供默认构造器.如果你希望用户能能够调用不带参数的构造器,那么你就必须自己实现一个.


extends[继承]:

java中的继承,和C++中是有差别的.比如JAVA不支持多重继承。但是JAVA可以通过implements来实现额外的接口.

Example:

DogDeriveClass extends AnimalBaseClass

{

};

这样DogDeriveClass就全盘继承了AnimalBaseClass中的所有方法;但是没有多重继承,那么如果还需要其它功能,那么则可以通过implements关键字来实现需要用到的接口.

Example:

DogDeriveClass extends AnimalBaseClass

Implements Shout, Run

{

     void Shot()

     {

     // Do shout something;

     }

    void Run()

    {

    // Do run something;

    }

};

从上面代码可以看到,虽然JAVA不支持多重继承,但是派生类可以通过实现接口的方式,来实现本身需要继承过来的功能.

Implements[实现]:

Implements关键字在class声明中使用,以指示所声明的类提供了在implements关键字后面的名称所指定的接口中所声明的所有方法的实现。

接口中的字段[变量]默认是public static final类型; //从接口的调用方式可以看出来. ImplementsInterface.MethedOfInterface();

接口中的方法不能是static,因为static不能被派生类重写,因为如果接口和派生类中都有一个static同名方法,那么根据static的调用方式可以看到

Interface.StaticMethed()即可调用,但是Interface中并没有该方法的实现,只有在具体实现类中有实现,如果有两个派生类都实现了同名的static方法,则该怎么调用?

虚拟机也不知道了!!所以不能这么做.

Example:

public class UserSurfaceView extends SurfaceView 
implements Android.view.SurfaceHolder.Callback  
{

     @Override 

     public void surfaceChanged(SurfaceHolder holder, int format, int with, int heigh)

     {

     //TODO Auto-generated method stub

     }

    @Override

     public void surfaceCreated(SurfaceHolder holder)

     {

     //TODO Auto-generated method stub

     }

     @Override

     public void surfaceDestroyed(SurfaceHolder holder)

     {

     //TODO Auto-generated method stub

     }

};

UserSurfaceView类就要实现SurfaceHolder对象中的Callback接口中所声明的所有方法的实现: surfaceChanged/surfaceCreated/surfaceDestroyed

从SDK上看到Android.view是包名,SurfaceHolder是一个public的interface, 而Callback就自然是public static interface[从调用方式即可看出来:Android.view.SurfaceHolder.Callback ]


Interface[接口]:

从上面implements关键字我们已经大概的了解到了关于java中接口的相关知识,下面看看接口的声明:

Example:

public interface Android.view.SurfaceHolder.Callback 

{

         void surfaceChanged(SurfaceHolder holder, int format, int with, int heigh);

        void surfaceCreated(SurfaceHolder holder);

        void  surfaceDestroyed(SurfaceHolder holder);

};

由于接口中的方法声明默认就是public的,因此不需要特意加上public修饰符.


reflect[反射]:

能够分析类的能力的程序称为反射器,JAVA中提供此功能的包是java.lang.reflect.它主要是针对工具构建者而不是应用程序员的.如果你只对编写应用程序感兴趣,而不想了解如何编写供其它java程序员使用的工具,那么就不要了解该机制.

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

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

2.在运行时构造任意一个类的对象;

3.在运行时判断任意一个类所具有的成员变量和方法[通过反射机制甚至可以调用private方法];

4.在运行时调用任意一个对象的方法;


java.lang.reflect包中包括下面几个主要:

0.Class类,描述类相关信息;

1.Field类,描述类的字段;

2.Method类,描述类的方法;

3.Constructor类,描述类的构造器;

3.Array类,描述类的创建动态数组的方法,该类中所有的方法都是静态属性;


下面我们开始介绍一些具体的用法:

A.Class类:

    在JAVA的Object类中声明了若干个可以在所有的JAVA类中改写的方法:

hashCode()/equals()/clone()/toString()/getClass()等,其中getClass()返回一个Class类型的对象.

    Class类和一般的类一样继承自Object, 其实体用于表达JAVA程序运行时的class和interface,以及enum, array, primitive, JAVA types和关键字void,当加载一个类时,或者当加载器[class loader]的defineClass()被JVM调用,便产生一个Class对象.

    Class是Reflection起源,针对任何你想查看的Class(类),必须先给该类生成一个Class的对象,然后才能通过这个对象调用相应的反射API。

    JAVA提供了多种途径来为一个Class类生成对应的Class对象:

    A,getClass(): Object类中的方法每个类都拥有该方法.

         Example:

         String str = "Test getClass()";

         Class cl = str.getClass();

    B,Class.getSuperclass(): Class类中的方法,返回该Class的父类的Class;

    C,Class.forName()静态方法:作用同上;

    D,类名.Class: 作用同上;

    E,primitive wrapper classer的TYPE语法:

        基本类型包装类的TYPE,Example, Integer.TYPE

        PS: TYPE的使用,只适合原生[基本]数据类型.

B.运行时生成instance

       要生成对象的实体,在反射机制中有两种方式:

       1.针对不带参数的构造器;

           Class类中的newInstance()实现该功能;

       2.针对带参数的构造器;

           Constructor类中的newInstance()方法,实现该功能.首先准备一个Class[]作为Constructor的参数类型.然后调用该Class对象的getConstructor()得到一个专属的Constructor对象,最后再准备一个Object[]作为Constructor对象里的newInstance()的实参.

           Example:

           Class c = Class.forName("DynamicTest");

           Class[]  pType = new Class[]{double.class, int.class};

           Constructor ctor = c.getConstructor(pType);

           Object[] obj = new Object[] {new Double(3.14), new Integer(119)};

           Object object = ctor.newInstance(obj);

           System.out.println(object);

 

C. 运行时调用Method:

      首先必须通过Class[]作为getMethod(String name, Class[])方法的参数类型, 然后再通过Object[]存放变量,最后调用Method对象的invoke(Object obj, Object[])方法.

D.运行时调用Field内容:

      修改Field不需要参数和变量, 首先调用Class的getField()方法并制定Field名称,获得特定的Field对象后便可以直接调用Field的get(Object obj)和Set(Object obj, Object value)方法.       


克隆[clone]:

其实这个方法的引入,就是为了实现类似C++中深拷贝的功能.在C++中参数的传递有:传值,传地址,传引用.

在JAVA中参数传递、=的赋值操作都是"引用传递[浅拷贝]",因此为了避免误操作,在需要传值的时候就不能进行传引用.

PS:如果类成员变量有数组或者复杂成员时需要进行深度克隆.浅拷贝只复制对象本身,并不复制该对象的引用、指针等成员所指向的地址.

       try{

        classObj = (classObject) super.clone(); // 通常情况下,这一行代码可以实现普通的克隆.

       }

       catch(CloneNotSupportedException e)

       {

            e.printStackTrace();

       }

        如果classObject类中包含了String name[]成员,那么就需要进行深度克隆

        try{

        classObj = (classObject)super.clone();

        classObj.name = (String)name.clone();

        }

       catch(CloneNotSupportedException e)

       {

            e.printStackTrace();

       }


final:

一般处于设计和效率的考虑使用final,第一final类不被继承、方法不被覆盖.第二final方法会被编译器在调用final的时候转入内嵌机制大大提高执行效率.第三防止被修改;

final类不能被继承,final类不能有子类,final类中的方法默认是final类型.

final方法不能被子类的方法覆盖,但可以被继承;

final成员变量表示常量,只能赋值一次,赋值后不能再改变;

final不能修饰构造器;

PS:父类的private方法是不能被子类方法覆盖的,因为父类的private方法默认是final的;

static:

JAVA中的静态字段和方法在功能上和C++的静态字段与方法是相同的.表示属于一个类而不是属于此类的任何特定对象的变量和函数.

调用方式:

className.staticMethod();

只要这个类被加载,那么JAVA虚拟机就能根据类名在运行时的数据区的方法区内找到它们;

静态字段在内存中只有一个拷贝,JVM只为静态字段分配一次内存,在加载类的过程中完成对静态字段的内存分配;


abstract:

抽象类,具有一个或多个抽象方法的类必须被声明为abstract.通常要尽可能的把通用字段和非常抽象方法移到抽象超类中.


Object类:

Object类是JAVA中所有类的最终的祖先------每一个类都由他扩展而来.


Internal Class内部类:

内部类是定义在其它类内部的类,一般使用内部类有四个原因:

1.内部类对象能够访问创建它的对象的实现---包括那些私有数据;

2.内部类能够隐藏起来,不为同一包中的其它类所见;

3.匿名内部类可以方便的定义运行时回调;

4.使用内部类在编写事件驱动的程序时用起来很方便;

PS:

本地内部类与匿名内部类的区别在于本地内部类有构造函数,而匿名内部类只能实例初始化。

Example:

      Thread thd = new Thread(

       new A(){//这里就是一个匿名内部类

                     }

       )

Proxy[代理]:

通过使用代理可以在运行时创建实现一组给定接口的新类.

代理类具有:

指定接口所要求的所有方法;

Object类定义的所有方法(toString, equals等等);

因为我们不能在运行时给这些方法定义新的代码.你必须提供一个调用处理器.调用处理器是实现了InvocationHandler接口的任意类的对象.该接口只有一个方法:

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

只要调用了代理对象上的任意一个方法,调用处理器的invoke方法就会被调用,带着Method对象和原调用的参数.随后调用处理器必须指出如何处理调用.

要创建一个代理对象,我们必须使用proxy类中的newProxyInstance方法,该方法有三个参数:

1>类加载器.

2>一个Class对象数组,每个元素都是需要实现的接口;

3>一个调用处理器;

如何定义处理器?

对结果代理对象能做些什么?

答案要取决于我们要使用代理机制解决的问题.代理可以用于很多目的:

a.路由对远程服务器的方法调用;

b.在运行程序中把用户界面事件和动作关联起来;

c.为调试目的跟踪方法调用;

详细参见:JAVA2核心技术卷1,P225














热点排行