Java基本语法

来源:互联网 发布:如何分期买手机淘宝 编辑:程序博客网 时间:2024/04/29 04:43

6.HelloWorld:第一个Java程序

import java.io.*;
public class HelloClass {
    public static void main(String args[]){
        System.out.println("Hello world!");
    }
}

将上边的代码保存为 Hello.java
在控制台编译使用命令 javac Hello.java
运行 java Hello.class 就可以看到输出.

其中 System.out.println() 是输出一行.类似的有
System.out.print()  输出但不换行.

字符串可以相加 如:
"abc" + "xyz"
也可以字符串和数字相加:
"abc" + 123

输入用 System.in.read() 例如:
int i;
try {
    i = System.read();
}catch(IOException e) {
    //..
}


小应用程序

import java.applat.Applet;
import java.awt.Graphics;
public class HelloApplet extends Applet {
    public void paint(Graphics g) {
        g.drawString("Hello World!", 0, 50);
    }
}

保存为 HelloApplet.java 
用命令 javac HelloApplet 编译生成文件 HelloApplet.class
再在HTML文件中加上如下语句:

<APPLET CODE="HelloApplet.class" WIDTH=200 HEIGHT=200> </APPLET>

用IE浏览器打开该HTML文件就可以看见结果.


小应用程序的生命周期

小应用程序是被浏览器加载的.
浏览器第一次加载该Java小应用程序时. 调用init()方法. 之后不管浏览器返回该网页多少次都不再调用.
调用 init()方法后. 接着浏览器调用 paint()方法.
再接着调用 start() 方法. start()方法在每次访问该HTML页时都会调用(例如向后返回到该页面)
当用户离开该页面(例如点击了其中一个超链接)时.调用 stop() 方法.
当浏览器被关闭时调用 destroy() 方法.


Java关键字

abstract    boolean    break    byte    case    cast*    catch    char
class    const*    continue    default    do    double    else    extends
final    finally    float    for    future*    generic*    goto*    if
implements    import    inner*    instanceof    int    interface    long
native    new    null    operator*    outer*    package    private    protected
public    rest*    return    abort    static    super    switch    synchronized
this    throw    throws    transient    try    var*    void    volatile    while
其中带*的是备用的

 

7. 数据类型及其它标记


8种基本类型:

boolean  只有两个值 true  false
byte   8位
char   16位
short  16位
int    32位
long   64位
float  32位
double 64位
它们都有缺省值 0(或false).


把基本类型包装成对象:

使用 Integer Long Float Double Short Byte Characte Void Boolean 类.
例如 :
Double dobj = new Double(0.1) //构造了一个对象.
但这样的包装器对象都不可更改对象的值. 所以它的值永远是0.1.
要取出它的值用 
double d = dobj.doubleValue();
另外. 这种基本类型包装器类中定义了从字符串中取值的静态方法. 如:
String s = "123";
int x = Integer.parseInt(s);



数组

大数类

Java有两个大数类 java.math.BigInteger 和 java.math.BigDecimal
BigInteger 表示不可变的任意精度的整数.
BigDecimal 表示不可改变的任意精度的10进制数.

 

定义一个数组

分三个步骤:
声明:  int IntArr[]; 或 int[] IntArr;
分配空间:  IntArr = new int[10];
向其中放入数据:  IntArr[0] = 1;  (对于内置类型的数组可以省略这步.使用缺省值0)
当然.这些步骤可以合并:
long arr[] = new long[100]; (对于内置类型.不初始化数组中的元素.则使用缺省的0)
或者用下边的写法不用写new关键字:
int iarr[] = { 1, 2 };  //3步合为1步

二维数组
int a[][] = { {1, 2}, {}, {} };

取数组的长度
数组名.length
Java中的数组一旦被创建.就不能再改变其大小.

数组赋值
直接用等号赋值只能使两个数组名引用同一个数组. 要真正把一个数组的元素拷贝到另一个用:
System.arraycopy(from, fromIndex, to, toIndex, count)
这要求目标数组有足够的空间来容纳新元素. 如:
int arr1[] = {1, 2, 3};
int arr2[] = new int[6];
System.arrcopy(arr1, 0, arr2, 0, 3); //将arr1的前三个元素复制到arr2的前3个处.

对数组排序用:
java.util.Array.sort(数组名);
如对上边的arr1排序用 Array.sort(arr1);

和排序类似的. Array类还定义了下边几个static方法:
static int binarySearch(Xxx[] a, Xxx v)   //二分查找
static void fill(Xxx[] a, Xxx v)  //用v填充a
static boolean equals(Xxx[] a, Object other)  //比较两个数组是否内容相等


数组列表 ArrayList
因为数组一旦构造后长度就不可改变.可以使用java.util.ArrayList使用可变长数组.



字符串 java.lang.String

构造方法:
    String()   //一个空串
    String(byte[] bytes)  
    String(byte[] bytes, int offset, int length)
    String(byte[] bytes, int offset, int length, String charsetName)
    String(byte[] bytes, String charsetName)
    String(char[] value)//用valeu数组的复制品创建字符串. 以后修改value数组不会修改到字符串
    String(char[] value, int offset, int count) //用value的一个区间的复制品创建字符串.
    String(int[] codePoints, int offset, int count)
    String(String original)   //创建original的一个副本.
    String(StringBuffer buffer) //用buffer缓冲区中字符序列的复制品构造字符串.
    String(StringBuilder builder)

被双引号扩起来的字符串. 都是java.lang.String类的实例.
String都是"常量". 即它在创建后就不能改变. 因为是常量.所以可以共享他们.
如:
   String s = "";
   s = "abc";

字符串可以用+连接.如:
s + "123" + 321 + true

String的其它方法:
public int length()  //返回此字符串的长度
public char charAt(int index)  //返回指定索引处的 char 值
public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
                      //将字符从此字符串复制到目标字符数组
public boolean equals(Object anObject)  //比较此字符串与指定的对象是否相等
public boolean equalsIgnoreCase(String anotherString)//不考虑大小写比较两String相等?
public int compareTo(String anotherString)  //按字典顺序比较两个字符串
public int compareToIgnoreCase(String str)  //不考虑大小写,按字典顺序比较两个字符串
public boolean regionMatches(int toffset, String other, int ooffset, int len)
                              //比较两个字符串的指定区域是否相等
public boolean regionMatches(boolean ignoreCase, int toffset, String other,
     int ooffset, int len) //比较两个字符串的指定区域是否相等. 第一个参数为true则不分大小写
public boolean startsWith(String prefix, int toffset)
                         //测试此字符串是否以指定前缀开始. toffset是开始比较的位置.
public boolean startsWith(String prefix)  //测试此字符串是否以指定前缀开始
public boolean endsWith(String suffix)  //测试此字符串是否以指定的后缀结束
public int hashCode()   //返回此字符串的哈希码。String 对象的哈希码按下列公式计算:
                     s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
public int indexOf(int ch)  //返回字符ch在此字符串中第一次出现处的索引.若找不到返回-1
public int indexOf(int ch, int fromIndex)  //从指定的索引开始搜索字符ch
public int lastIndexOf(int ch)  //返回字符ch最后一次出现的索引.若找不到返回-1
public int lastIndexOf(int ch, int fromIndex)  //搜索时从fromIndex处开始进行后向搜索
public int indexOf(String str)  //返回子串str第一次出现的索引
public int indexOf(String str, int fromIndex)
public int lastIndexOf(String str)
public int lastIndexOf(String str, int fromIndex)
public String substring(int beginIndex)  //取一个子串.子串从参数位置到结束.
public String substring(int beginIndex, int endIndex)
public CharSequence subSequence(int beginIndex, int endIndex) //返回一个新的字符序列
public String concat(String str)  //将指定字符串联到此字符串的结尾.返回新字符串
public String replace(char oldChar, char newChar) //替换. 返回替换后的新串.
public boolean matches(String regex)  //是否匹配一个正则表达式?
public boolean contains(CharSequence s)  //是否包含字符序列s?
public String replaceFirst(String regex, String replacement)
       //用 replacement 字符串替换此字符串匹配给定的正则表达式的第一个子串
replaceAll
public String replaceAll(String regex, String replacement) //替换所有匹配子串
public String replace(CharSequence target, CharSequence replacement)
            //用新字符序列替换源字符串中旧的字符序列
public String[] split(String regex, int limit)  //根据匹配给定的正则表达式来拆分此字符串
public String[] split(String regex)
public String toLowerCase(Locale locale)  //转换为小写.规则用 Locale给定
public String toLowerCase()   //转换为小写. 使用默认语言环境的规则
public String toUpperCase(Locale locale)  //转换为大写. 和上边类似
public String toUpperCase()
public String trim()  //返回字符串的副本,去掉了源串的前导空白和尾部空白
public char[] toCharArray()  //转换为一个字符数组
public static String format(String format, Object... args)
          //使用指定的格式字符串和参数返回一个格式化字符串
public static String format(Locale l, String format, Object... args)
public static String valueOf(Object obj)  //返回 Object的字符串表示形式
public static String valueOf(char[] data)  //返回 char 数组参数的字符串表示形式
public static String valueOf(char[] data, int offset, int count)
                    //返回 char 数组的特定子数组的字符串表示形式
public static String copyValueOf(char[] data, int offset, int count)
public static String copyValueOf(char[] data)
public static String valueOf(boolean b)  //返回 boolean 参数的字符串表示形式。
public static String valueOf(char c)
public static String valueOf(int i)
public static String valueOf(long l)
public static String valueOf(float f)
public static String valueOf(double d)


 


注释

javadoc注释的格式为  /**    */

文档注释的格式:

类注释必须直接放在class定义之前.
方法注释必须直接放在方法定义之前.  还可以用 @param 解释的参数. 用@return解释返回值. 用@throws
       解释方法可能抛出的异常.
字段注释必须直接放在字段定义之前.字段注释通常只用作静态常量的注释.
类注释中还可以用:
   @author说明作者.
   @version说明版本.
   @since说明"始于..".
   @deprecated说明此类/方法/变量不应该再被使用.
   @see添加一个超级连接.指向"参见..."
要对包进行注释. 可以在包目录中添加一个"package.html"来说明本包.
要对所有源文件进行概述. 可以在包含所有源文件的父目录下添加一个"overview.html".


8. 方法

格式为:
访问说明符  修饰符  返回值  方法名 (参数) throws 异常列表

其中
访问说明符
public  private  protected  意义和c++中的一样.
缺省时. 表示该方法只能被当前包中的类访问.

修饰符
static  意义和c++的一样.
abstract 抽象方法. 就是只声明而没有定义. 和c++的纯虚函数一样.
final   它修饰的方法不允许被子类覆盖.
Native  它修饰的方法和抽象方法一样只有声明而没有定义.它的定义一般需要其它语言(如c++)来写.
synchronized    同步.

java方法的参数(返回值)传递时. 对8种基本类型使用传值. 其它的传引用.

java循环中使用的 continue 和 break 语句可以跳转到某一标号处. 和c++不同.

 

9. 使用表达式

运算符优先级列表(同一行的优先级一样)
高优先级   .  []  ()
一元      +  -  ~  !  ++  --
乘除      *  /  %
加减      +  -
移位      <<  >>  >>>
关系      <  <=  >  >=
等于      ==  !=
按位      &(按位与)  ^(按位异或)
按位      |
条件或    &&  ||
问号运算   ?:
赋值      =

java运算符和c++的区别:
java中.计算顺序是确定的.
在java中 取余%  ++  -- 可以用于所有内置类型. 而在c中它们只用于整数.
java的关系运算和相等运算的结果是boolean的. 而c中它们的结果是int型的.
java支持字符串的本地运算.包括串联接和串赋值.
java有两种右移运算符 >>  >>>  来指出对有符号数右移时左边补0还是补符号位的值.


类型转换

java中的隐式类型转换只有在不损失精度和不改变值的情况才进行. 其它情况只能显式强制转换.否则报错.

并不是所有的类型之间都可以强制转换. boolean就不能和其它类型进行转换.所以要用类似下边的办法:
boolean b;
int i = b ? 1 : 0;

类对象的向下类型转换要显式转换:
if (a instanceof Abc)
    Abc x = (Abc)a;  //若向下转换失败. 会抛出异常.



10. 控制流

根据一个布尔表达式的结果来转移程序. 要注意java中的boolean类型和其它类型不能转换.
boolean 类型可以做的运算有:
!  &  |  ^   &&   ||  ==   !=   =   ?:
关系运算:
<  <=  >  >=
相等运算:
==   !=  //在java中.对于内置类型则比较它们的值是否相等.对于对象.则看它们是否引用了同一对象.

 

 11. 类


类声明格式:
public(或缺省)  final(或缺省)  abstract(或缺省)  class  类名  extends  超类名   implements  接口名

public的类可以在任何地方被使用和扩展.不受包的限制.否则只能被当前包中的其它类使用和扩展.
public的类名必须和源文件的名字一致.
所以如果有
public class Abc {}
则它的源文件名一定是 Abc.java

final类. 它不会有任何子类.
如 final class Abc{}

abstract. 表示是一个抽象类.至少有一个方法是不完整的. 所以不能创建它的对象.
如 abstract class Abc{}

Java中没有拷贝构造函数了. 要得到一个对象的深拷贝则要调用 clone()方法(细节见后边).
Java的对象间赋值= 只是让两个引用指向了同一个对象
.




超类

继承的语法:
class 类名 extends 超类 { }

如果没有写继承了哪个超类.则缺省的继承 java.lang.Object
java不能多继承.




构造器

构造器的访问属性可以为private. 这样就只能使用类的静态方法.
构造器不能是 native abstract static synchronized final
Java方法的参数如果是类类型的. 则传递引用. 但这和c++的传引用不同. 而实际上传递的是引用的值.
总之. Java的引用相当于c++中的指针.

类的字段. 如果没有在构造器中初始化. 则会被隐式初始化. 内置类型为0或false. 类类型为null.
但是在方法中. 局部变量不会被自动的隐式初始化.

如果类没有提供任何构造器. 则会自动生成一个默认构造器. 这个构造器会初始化类的字段.

类中声明字段时. 可以同时给该字段初始化. 如:
class A {
   private int x = 2;
}
类中还可以有初始化器.即 {  } 扩起来的语句. 如:
class A {
   private int x;
   { x = 2; }
}
可见在Java中类的字段有多种初始化办法. 它们的调用顺序如下:
构造对象时. 先初始化所有字段为默认值. 即 0. false. null.
再按照字段声明的次序执行这些字段的初始化语句和初始化块.
再执行构造器.

在一个构造器中调用本类的其它构造器用this().如下:
class A {
    public A() { ... }
    public A(int x) { this(); } //this()必须是构造器的第一个语句. 这样做可以共同使用代码.
}


对于static字段的初始化. 它们在定义的时候可以初始化. 如:
class A{
    static int x = 2;
}
或者使用静态初始化块. 如:
class A{
    static int x;
    static { x = 2; }
}
如果static字段没有被显式的初始化. 则自动初始化为默认值(0. false. null).
static字段的初始化时间是类第一次被加载的时候. 顺序是它们在类中声明的顺序.

特殊变量 super
用来访问超类. 如子类覆盖了超类的方法后.要在子类中调用超类版本的可以用 super.XX();
在构造函数中调用超类的构造方法也要用 super(参数);


字段

成员变量的访问修饰符public protected private和c++的意义一样. 
缺省时表示只允许被本包内访问.
protected字段和public字段也可以在被同一个包中被访问.
static的意义也和c++中一样. 不过java的常量用 final修饰. 和c++的const一样.


finalize方法

它是java.lang.Object类中的方法. 是protected的.
缺省时这个方法是空的. Java运行系统在垃圾回收时在对象被撤销之前调用这个方法. 但由于垃圾单元
回收的时间是不确定的.所以不能过分依赖它(这和c++的析构函数不同). 
而只能是"在对象被撤销之前"做一些处理.例如可以在这里关闭构造方法中打开的套接字.
如果要重写该方法.访问属性只能是protected或更低.


///////////////////////////////////////////////////////////////////////////////
// Object类
//
// 构造方法:
//     public Object()
// 其它方法:
// public final Class<? extends Object> getClass() 
//   //返回一个对象的运行时类(java.lang.Class 对象)。
//   //该 Class 对象是由所表示类的 static synchronized 方法锁定的对象。
// public int hashCode()  //返回该对象的哈希码值.用来支持哈希表.
//   //哈希函数的约定是:
//   //   在程序执行时对同一个对象多次调用该方法应该返回相同的整数.但一个程序
//   //   的多次运行中对象的哈希码值可以不同.
//   //   如果两个对象根据 equals(Object)方法比较相等. 则两对象的哈希值应该相同.
// public boolean equals(Object obj)  //比较两个对象是否相等.
//     但在Object类中实现为判断2者是否引用同一个对象. 所以自己的类需要的时候要覆盖它.
//     自己写 equals 方法时应符合下边的约定:
//         测试this和obj是否引用同一个对象. if(this==obj) return true;
//         测试obj是否为null. if(obj == null) return false;
//         测试this和obj是否属于同一个类. if(getClass != obj.getClass()) return false;
//         再把obj转换为本类类型后. 比较this和obj的所有字段. 如果本类有基类.先比基类部分如:
//             if (!super.equals(obj)) return false;
// protected Object clone() throws CloneNotSupportedException //返回一个副本
// public String toString()  //返回该对象的字符串表示. 在Object类的实现中返回字符串:
//       getClass().getName() + '@' + Integer.toHexString(hashCode())
// public final void notify()  //唤醒在此对象监视器上等待的单个线程
// public final void notifyAll()  //唤醒在此对象监视器上等待的所有线程
// public final void wait()
// public final void wait(long timeout) throws InterruptedException
// public final void wait(long timeout, int nanos)
//         导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法
//         或者超过指定的时间量
// protected void finalize() //当垃圾回收器回收当前对象时.垃圾回收器调用此方法
/////////////////////////////////////////////////////////////////////////////


package声明. 但有两个要求:
包中的类所在文件都在同一目录下.属于包的源文件要放在包名对应的目录名中.
这样编译以后的输出文件也在对应的目录.以便用 import包含的时候能找到它们.

package语句必须是文件中的第一个语句.(
该句之前只能有空白或注释).
如: package Abc;

引入包中某个类.
如: improt Abc.Xyz;

引入整个包.(之后可以使用该包中的所有的类)
improt Abc.*;

不通过引入而直接使用类
null包和放在同一物理目录中的类可以不经过引用而使用. 所以这时可以直接使用.
如果类在包中可以用 包名.类名 的形式使用类.

标准的Java包有:
java.applet  用于创建小应用程序
java.awt     用于编写平台无关的图形用户界面应用程序
java.io      用于输入输出处理
java.lang    一些基本Java类. 这个包中的类是被隐式引入的.用户可以不引入而直接使用其中的类.
java.net     用于建立网络连接
java.util    一些工具和数据结构

5.3 Class类 - core java 

Class 类的实例表示正在运行的 Java 应用程序中的类和接口.
每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象.
基本类型(如int)和关键字 void 也表示为 Class 对象.
Class类没有公共构造方法. Class 对象是在加载类时由 Java 虚拟机自动构造的.

可以通过 对象.getClass()类.class 得到一个对象或类的Class类.如:
Class c = void.class  //void也可以
Class c = int.class
String s = new String("abc");  Class c = s.getClass()
也可以用一个类名字符串得到一个类的Class对象. 使用Class类的静态方法:
public static Class<?> forName(String className) throws ClassNotFoundException
如:  Class c = Class.forName("java.lang.Thread")


Class类的方法:
public String toString() //转换为字符串。字符串的表示形式为字符串 "class" 或"interface"   
                         //后面紧跟一个空格,然后是该类的完全限定名
public static Class<?> forName(String className) throws ClassNotFoundException
public static Class<?> forName(String name, boolean initialize,
                    ClassLoader loader) throws ClassNotFoundException
       //取的指定类名className对应的Class对象. 其中参数:
         name - 所需类的完全限定名
         initialize - 是否必须初始化类
         loader - 用于加载类的类加载器
public T newInstance()  //创建此 Class 对象所表示的类的一个新实例
public boolean isInstance(Object obj)  //判定指定的 Object 是否与此 Class 所表示的对象 

                     //赋值兼容。此方法是 Java 语言 instanceof 运算符的动态等效方法
public boolean isAssignableFrom(Class<?> cls)  //判定此 Class 对象所表示的类或接口与指
                   //定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口
public boolean isInterface()  //判定指定的 Class 对象是否表示一个接口
public boolean isArray()  //是否表示一个数组类
public boolean isPrimitive()   //是否表示一个基本类型(8个基本类型和void)
public boolean isAnnotation()  //是否表示一个注释类型
public boolean isSynthetic()  //是否表示一个复合类
public String getName()  //返回此 Class 对象所表示的实体的名称
   //若表示的是基本类型或void. 则返回"int"之类. 若是类或接口.则返回"java.lang.String"之类.
   //若表示数组类型. 则返回几个"[" + "编码". [的个数是数组嵌套层数. 编码是:
   //boolean(Z) byte(B) char(C) double(D) float(F) int(I) long(J) short(S) 
   //类或接口(L类名)
public ClassLoader getClassLoader()   //返回该类的类加载器。基本类型返回null
public Class<? super T> getSuperclass() //返回表示的实体的超类的Class对象.
                  //对于没有超类的实体(Object类.接口.基本类型.void)该方法返回null.
                  //对于数组. 返回Object.class
public Type getGenericSuperclass()  //此对象所表示的类的超类. 对没有超类的返回null.
                                    //对数组返回Object.class
public Package getPackage()  //获取此类的包
public Class[] getInterfaces()  //返回它表示的class或interface实现了的接口的Class数组
public Type[] getGenericInterfaces() //返回它表示的class或interface实现了的接口数组
public Class<?> getComponentType()  //返回表示数组的组件类型的 Class
public int getModifiers() //返回此类或接口以整数编码的 Java 语言修饰符(如public.final等)
public Object[] getSigners()  //获取此类的标记
public Method getEnclosingMethod() //若表示的是某方法中的本地类或匿名类.返回该Method对象.
public Constructor<?> getEnclosingConstructor()
         //若表示构造方法中的一个本地或匿名类,则返回 Constructor 对象
public Class<?> getDeclaringClass()//若表示的类或接口是另一个类的成员,则返回该类的Class
public Class<?> getEnclosingClass()  //返回基础类的立即封闭类
public String getSimpleName()  //返回源代码中给出的基础类的简称
public String getCanonicalName() 
             //返回《Java Language Specification》中所定义的基础类的规范化名称
public boolean isAnonymousClass()  //是否表示一个匿名类
public boolean isLocalClass() //是否表示一个本地类
public boolean isMemberClass() //是否表示一个成员类
public boolean isEnum()  //是否表示一个枚举
public T[] getEnumConstants()  //若表示枚举. 则返回其元素
public T cast(Object obj) //将obj强制转换成此 Class 对象所表示的类或接口
public <U> Class<? extends U> asSubclass(Class<U> clazz)
      //强制转换该 Class 对象,以表示指定的 class 对象所表示的类的一个子类public Class[].

getClasses()  ///
public Field[] getFields()  //返回表示public字段的 Field 对象的数组
public Method[] getMethods() //返回表示public方法的 Method 对象的数组
public Constructor[] getConstructors() //返回表示public构造方法的Constructor对象的数组
public Field getField(String name) //根据指定的字段名返回一个表示public字段的Field对象.
public Method getMethod(String name, Class... parameterTypes)                     

                                                //根据名字和参数返回Method
public Constructor<T> getConstructor(Class... parameterTypes) //返回Constructor
//未完. 太多了

5.4 反射 -core java

能够分析类的能力的程序称为反射器. Java提供此功能的包是 java.lang.reflect包.
该包中的三个类Field Method Constructor 分别表示字段.方法和构造器.
这三个类都有getName方法来返回表示的实体的名字. 还有返回类型和返回参数类型等方法.
所以使用反射可以:
    运行时分析类的能力
    运行时探查对象.比如只写一个toString方法供所有的类使用
    实现通用数组操作代码
    使用Method对象.它类似于c++中的函数指针

使用反射器分析一个类的例子:
improt java.lang.reflect.*;
import javax.swing.*;

public class ReflectionTest {
    public static void main(String[] args) {
        string name;
        if (args.length > 0) name = args[0];
        else name = JOptionPane.showInputDialog("Class name: ");
        try {
            Class cl = Class.forName(name);  //通过类名得到Class对象
            Class supercl = cl.getSuperclass(); //取父类的Class对象
            System.out.print("class " + name);
            if (supercl != null && supercl != Object.class)
                System.out.print(" extends " + supercl.getName());
            System.out.print("/n{/n"};
            printConstructors(cl);
            System.out.println();
            PrintMethods(cl);
            System.out.println();
            PrintFields(cl);
            System.out.println();
        } catch (ClassNotFoundExcption e) { e.printStackTrace(); }
        System.exit(0);
    }

    public static void printConstructors(Class cl) {
        Constructor[] constructors = cl.getDeclaredConstructors(); //取构造方法数组
        for (int i=0; i<constructors.length; i++) {
            Constructor c = constructors[i];
            System.out.print(Modifier.toString(c.getModifiers()));
            System.out.print("    " + name + "(" );
            Class[] paramTypes = c.GetParameterTypes(); //取构造方法参数类型的数组
            for (int j=0; j<paramTypes.length; j++) {
                if (j > 0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            System.out.println();
        }
    }

    public static void printMethods(Class cl) {
        Method[] methods = cl.getDeclaredMethods(); //取其它方法的数组
        for (int i=0; i<methods.length; i++) {
            Method m = mothods[i];
            Clsss retTyeps = m.getReturnType(); //方法的返回类型的Class
            String name = m.getName();
            System.out.print(Modifier.toString(m.getModifiers()));
            System.out.print("   " + retType.getName() + " " + name + "(" );
            Class[] paramTypes = m.getParameterTypes(); //方法的参数类型的数组
            for (int j=0; j<paramTypes.length; j++) {
                if (j > 0) System.out.print(", ");
                System.out.print(paramTypes[j].getName());
            }
            Ststem.out.println(");"};
        }
    }

    public static void printFields(Class cl) {
        Field[] fields = cl.getDeclaredFields();
        for (int i=0; i<fields.length; i++) {
            Field f = fields[i];
            Class type = f.getType();
            String name = f.getName();
            System.out.print(Modefier.toString(f.getModifiers()));
            Ststem.out.print("   " + type.getName() + " " + name + ";" );
        }
    }
}

 

通过Field(表示字段). 可以查看某对象的该字段的值. 使用如下方法:
Object get(Object obj)  //对于类类型的字段
int getInt(Object obj)  //对于内置类型的字段用类似这样的方法.若用get()则返回的是包装后的对象
如:
class A { public String x; }
A a = new A;
Class c = a.getClass();
Field f = c.getDeclaredField("x"); //取得x字段的Field对象.
Object o = f.get(a); //这样就得到了a.x的值.
这种用法很像c++中 通过一个指向数据成员的指针和一个对象来的到该对象对应的成员的值.
对应的. 有get()也有set()来设置obj对象的某个字段:
void set(Object obj, Object value)
void setInt(Object obj, int value) //对于内置类型的字段用这个方法


用Method(表示方法). 可以执行某对象的该方法. 这要使用Method类的方法:
Object invoke(Object obj, Object... args)
这类型于c++中的指向成员函数的指针. 给它帮定了一个对象和函数参数. (如在Loki库中的Functor)
如果Method对象表示的是静态方法. 则它就相当于一个c函数指针. 调用invoke()时第一个参数传null.

 

6.接口和内部类 - core java

6.1 接口

接口用来避免c++的多继承. 它相当于c++的纯粹抽象类. 它的成员只能是抽象方法和静态常量.

定义接口时如下:
public(或缺省) interface 接口名 extends 接口列表 { }
各个部分和定义class时的意义一样.

接口中声明的变量都是 public final static的.


使用接口

如: class A implements B{ ... }

如果接口中的某个方法带有异常列表.在派生类中覆盖它时方法头中可以不带异常列表而在方法体中直接抛出
异常. 如果覆盖时方法头中带有异常列表则列表中的异常类型只能是接口中列出的异常类型的子集. 实际上
不管覆盖时写的异常列表是什么.在方法中总是可以抛出接口的方法声明时指定的异常. 所以覆盖时通常就不
再带那个异常列表了.

instanceof 关键字
用来检查对象是否属于某个类或接口.




6.2 clone方法

要得到一个对象的深拷贝. 要调用clone()方法. 如:
A a = new A;
A b = a.clone();
但clone方法并不这么简单. 它是Object类的一个protected方法. 所以在A类和A的派生类以外调用这个
方法是不行的. 而且在Object的clone方法的实现中只是对所有的字段进行浅拷贝. 如果A类某个字段是类
类型的. 则这样的浅拷贝可能不是我们希望的结果.
所以要能正确的调用A的clone方法必须:
    让A类实现 Cloneable接口. 并用public访问修饰符重新定义clone方法.
但Cloneable接口实际上并没有声明clone方法. 这个接口只是作为一个标记.证明一个类可以调用clone().
如果对一个没有实现Cloneable接口的类调用clone方法.会抛出CloneNotSupportedExption异常.

定义自己的clone方法时如下:
class A extends B implents Cloneable {
    C c;
    int x;
    public Object clone() {
        try {
            A cloned = (A) super.clone();
            cloned.c = (C) c.clone();
            return cloned;
        } catch (CloneNotSuportedException e) { return null; }
    }
}


6.3 内部类

先看一下c++的嵌套类
class LinkList {
public:
    class Iterator { ... };
private:
    class Link { ... };
};
这样可以通过 LinkList::Iterator 来访问内部的Iterator类. 这样做可以避免名字冲突.
而私有的 LinkList::Link 类在LinkList类外部则是不可访问的. 把内部的Link类的数据成员弄成
public的也是安全的. 因为只有在LinkList类内才能访问它.

Java的内部类是指定义在其它类内部的类.它和c++的嵌套类不同.
Java的内部类的对象持有一个隐式引用.指向那个实例化它的外部类的对象. 通过这个引用我们可以访问外部
对象的全部状态(包括私有).  只有当内部类是static的时内部类的对象没有这种隐式引用. 这时它就和c++
的嵌套类是相似的.

只有内部类可以是 private 访问修饰符的.而外部类只能是public或默认的. 如:
class A {
    private class B { .. } //private使得内部类B只能在A内访问.
}

再看看内部类对象如何持有一个外部类对象的指针:
class A {
    private int x = 3;
    void funa {
        B b = new B; // 构造内部类B的对象.
              // 实际上编译器隐式的在B的构造器中加上了一个隐藏的参数 A 如: public B(A out)
              // 并在构造b时实际上这里编译器是调用了 new B(this) .这样使b就持有了一个指向
              // 它的外部类A 的对象的引用. 正是这个引用所指向的A对象创建了b.
              // 可以在构造b时显式的指出是哪个外部类对象创建了该内部类对象.而不一定就用this.
              // 所以上边的 new B 可以写为 this.new B
        b.funb();
    }
    private class B {
        public void funb() { x++; }  //此处的 x 为它的外部类A的实例的x字段.
             //要取得b所持有的外部类的引用可以用: A.this
             //所以上边的x++ 可以写为:  A.this.x++
    }
}

内部类只是一种语法. 编译之后它和普通类对于虚拟机来说是一样的. 编译内部类的输出文件为:
外部类名$内部类名.class 
如上边的内部类B 编译生成的文件为 A$B.class


局部内部类

局部的内部类是指定义在其它类的方法中的类. 如:
class A {
    public void fun() { 
        class B { ... }   //一个局部的内部类
    }
}

局部内部类不需要public private等修饰.因为它只能在该方法内被使用.即使是A的其它方法也不能使用B.
局部内部类是一种特殊的内部类. 所以它的对象也持有外部类的引用. 也可以访问外部类的成员.
而且局部内部类还可以访问定义在该方法中的final局部变量
. 例如:
public void fun(final double d) {
    class B {
        public void f() { double x = d; } //使用fun的局部final变量
    }
    B b = new B;
    //..........
}

 

匿名内部类

匿名内部类是一种特殊的局部内部类. 因为有时我们只要为局部类创建唯一的一个对象. 这时就省略了类名:
public void fun() {
    ActionListener a = new ActionListener() {  //定义匿名类的同时创建匿名类的实例.
                                       //在这里ActionListener是该匿名类的超类(或接口)
        public void actionPerformed(ActionEvent e) { ... }
    }
    addActionListener(a);
}
         

静态内部类

静态内部类是在定义内部类的时候使用了static关键字. 这样内部类的对象就不再持有外部类对象的引用了.
如果内部类不需要访问外部类的成员就应该定义成静态内部类. 这就和c++中的嵌套类一样了. 这样可以避免
名字冲突.


6.4 代理


原创粉丝点击