JAVA语法复习

工作原理
1)编写.java文本文件;
2)通过编译器编译为.class二进制文件;
3)使用JAVA虚拟机执行.class文件,不同平台对应不同虚拟机;
System.exit:main方法结束不等于整个程序的真正结束,可能还有线程在运行着,调用System.exit()才达到程序的真正结束。


面向对象原理
单继承,多接口实现;一般,继承主要用在一个系列的对象抽象;接口主要针对功能的抽象;
JAVA语言中,并非所有的变量都是对象,基本的数值类型(char,short,int,long,float,double,boolean)除外,可能是为了运行速度,编译器没有将这些类型编译为对象;
对象Object是所有对象的祖宗;
对象Class保存一个对象的类型信息,也可以是基本的数值类型;


数据类型
int         4B
short       2B
long        8B
byte        1B
float       4B (后缀f,F)
double      8B (后缀d,D)
char        2B
boolean     1B
前缀:
0x:十六进制 (指数用p,十进制用e)
0:八进制


变量命名
字母(a-zA-Z)、下划线(_)开头,后续字母可以是字母、数字、下划线,不能是关键字或者保留字。


关键字
abstract, assert, boolean, break, byte, case, catch, char, class, const, continue, default, do, double, else, extends, final, finally, float, for, goto, if,

implements, import, instanceof, int, interface, long, native, new, null, package, private, protected, public, return, short, static, strictfp, super, switch,

synchronized, this, throw, throws, transient, try, void, volatile, while
其中,const和goto是保留关键字。


注释
//行注释


运算符
算术运算:+、-、*、/、%;++、--、+=、-=;
关系运算:>、<、==、>=、<=、!=、!、&&、||;
位运算:&、|、^、~、>>、>>>、<<、<<<;


流程控制
if ... else ...
(...) ? ... : ...;
switch  只能接受byte、short、char、int四种,不能接受long类型。
for
for each
while
do...while


参数传递
基本数据类型按照值传递,对象按照引用传递;String对象没有修改该对象的方法,如果要通过引用修改可以使用StringBuilder或StringBuffer;


面向对象
类加载:static字段、一般字段、构造函数字段;(注意:static成员是类加载器加载的,是线程安全的;)
继承;
接口;
内部类、匿名内部类用途:使用一个对象去做任务处理,但是该对象以后也不需要用到;这样在一个类A内部定义一个内部类B,这样类B可以访问类A的数据,外界并不知道有类B的存在;
异常继承时候,父类与子类的异常声明可以不同,但是子类的异常必须在父类的异常范围之内,也就是父类的异常必须可以引用子类的异常;
方法继承时候,如果需要覆盖,方法名称、形参类型、返回类型必须相同;


访问修饰符
           当前对象    同一个包中子类/非子类     其它包中子类/非子类
private    yes         no/no                     no/no
protected  yes         yes/yes                   yes/no
默认       yes         yes/yes                   no/no
public     yes         yes/yes                   yes/yes


对象比较
使用==比较的是引用;使用equals默认比较的也是对象的引用,但是,经过重载的equals可以按照我们需要去比较特点字段;
String类重载了equals与hashCode,而StringBuilder与StringBuffer没有经过重载,因此使用equals比较StringBuilder与StringBuffer实际比较的是引用;
注意:重载equals必须同时重载hashCode,这两个方法必须保持同步,即equals与hashCode同真假;


对象序列化
继承接口Serializable即可以实现对象序列化,默认是序列化与反序列化的结果是相同的(引用被序列化后再反序列化回来还是跟之前相同的);
一般序列化后,要定义字段serialVersionUID,eclipse自动可以生成;作用是保持序列化与反序列化时候的版本兼容,如果不定义该字段,当出现反序列化时候内容不同时,可能会报错;
transient关键字可以使该字段不进行序列化;


对象克隆
继承接口Cloneable,然后覆盖Object类的clone()方法进行克隆的声明;默认是浅拷贝,若字段是引用类型,则需要手动在clone()方法里面人工进行new一个对象;
数组默认支持克隆,但是数组的数组(二维数组以上)不支持直接使用克隆;


异常
异常的结构
Throwable
        |
    Error  Exception
                            |
               IOException等  RuntimeException

异常的分类
1)未检查异常
RuntimeException和Error及其子类。
这类异常不需要显式捕捉,一旦发生,它自动会抛出来,然后程序终止;当然,你也可以进行捕捉,这样程序就可以继续运行;
2)已检查异常
Exception及其子类
由于Exception派生的子类及Exception类多是已检查异常,所以,Throwable类也属于已检查异常;这类异常必须进行捕捉,否则编译不能通过。

声明已检查异常
例:public FileInputStream(String name) throws FileNotFoundException

抛出已检查异常
例:throw new Exception("message");

捕获异常
如果不捕获的话,程序就会终止。有些时候,出现了异常,但是,我们不需要终止程序,那么就需要捕获异常。
try {
    // 可能抛出异常的代码
} catch(异常类型 e) {
    // e.printStackTrace(); // 打印异常堆栈
    // 处理
}
// catch语句是从上到下执行的,具体的异常应该放在上面;

传递异常
将异常传递下去,这样才能不会被覆盖;
try {
    // access the database
} catch(SQLException e) {
    throw new ServletException("database error.", e);
}

finally子句
finally子句是一定会执行的,该子句主要用于回收一些资源。


泛型(属于底层代码,不常用)
JAVA虚拟机中没有泛型,只有普通类与方法,使用泛型主要是为了方便类型转换;还有泛型可以限定对象引用的使用;所有,泛型了解使用即可,不需要深究;
泛型包含两种:泛型类、泛型方法;泛型类主要用于对某个不确定类型的字段进行操作;泛型方法是指static方法中使用了泛型参数;

泛型的翻译
翻译泛型表达式
A a = new A();
a.setT("generic programming.");
String str = a.getT(); // 翻译为:String str = (String) a.getT();
翻译泛型方法
public static T getMiddle(T[] a) // 翻译为:public static Object getMiddle(Object[] objects)
public static   T getMiddle(T[] a) // 翻译为:public static Comparable getMiddle(Comparable[] a)
// 默认是转化为左边第一个类型,所有尽量将范围大的类型放到前面;
复杂一点的桥方法:
class A {
 
 private T t;
 
 public void setT(T t) {
  this.t = t;
 }
 public T getT() {
  return t;
 }
}
class B extends A {

 

 public void setT(String t) {
  super.setT(t);
 }
}

// 翻译后:
class A { // 父类翻译后肯定是Object
    private Object t;
  
    public void setT(Object object) {
 t = object;
    }
  
    public Object getT() {
 return t;
    }
}
class B extends A {
    public void setT(String string) { // 子类肯定它的父类是String
 super.setT(string);
    }
  
    public volatile void setT(Object object) { // 桥方法,外界还是认为是Object
 setT((String) object);
    }
}
// 调用:
A a = new B();
a.setT("generic programming."); // 翻译为:b.setT((Object) "generic programming.");

不能使用泛型的情况
不能使用泛型继承异常。
例如:public class Problem extends Exception {...}。
不能在catch(...)中,使用catch(T t)。
异常声明中可以使用泛型。
例如:public static void doWork(T t) throws T {...}。

不能用泛型数组
A[] arr = new A[5]; // 擦除后为:A[] arr = new A[5];

不能将泛型类型实例化。
class A {
 a = new T(); // 擦除后是a = new Object();我们本意却不是这个。
 ...
}

类的静态字段不能使用泛型;

当泛型类型擦除后,创建条件不能产出冲突。
例如:public boolean equals(T t) {...}

 

类型限定
子类型限定<? extends Employee>,可以读,不能写。
Pair<? extends Employee> pair1 = null; // ?是Employee的子类,子类可能很多,不确定有几个。
Pair<Manager> pair2 = new Pair<Manager>();
pair1 = pair2;
pair1.getFirst(); // 操作成功,因为是“(? extends Employee) pair1.getFirst();”,
  // 相当于是“(Employee) pair1.getFirst();”。
pair1.setFirst(new Manager()); // 编译通不过,因为是“pair1.setFirst(? extends Employee);”
  // 相当于是“pair1.setFirst(?);” 不确定的类型。

超类型限定<? super Employee>,可以写,不能读;刚好和上面相反。

无限定通配符<?>,可以读,不能写;读的时候直接转型为Object。


反射(属于底层代码,不常用)
对象产生于类,而在JAVA虚拟机里面还保存着对类的描述,这个描述是一个Class的对象;类信息被加载到虚拟机,就会产生一个Class对象,用以描述这个类的信息;
通过这个Class对象可以解析类的结构,这个Class对象可以从类信息来(例如:Employee.class),也可以从对象来(例如:emp.getClass());
通过这个Class对象可以引用具体对象的字段、方法、构造器,可以完全操作一个对象;
.class: 应该是一个指向类的Class对象的指针。
forName(): 会调用当前线程所在的ClassLoader来装载一个类的Class实例。
注意:基础类型也可以这样使用“int.class”;


类加载器(属于底层代码,不常用)
java中的类是动态加载的,即引用到了才会被加载;
// 三种加载方式示例
class A{}
class B{}
class C{}
public class Loader{
    public static void main(String[] args) throws Exception{
       Class aa=A.class;
       Class bb=Class.forName("B");
       Class cc=ClassLoader.getSystemClassLoader().loadClass("C");
    }
}

系统内默认的类加载器
Bootstrap ClassLoader (加载rt.jar)
 |
 ExtClassLoader (加载jre/lib/ext/)
  |
  AppClassLoader (加载claspath)

//ClassLoader实现:查找类,从父加载器向上遍历,找不到就调用当前自定义的加载器;
protected ClassLoader() {
 SecurityManager security = System.getSecurityManager();
 if (security != null) {
     security.checkCreateClassLoader();
 }
 // 自己实现的类加载器,默认是用系统类加载器的。
 this.parent = getSystemClassLoader();
 initialized = true;
}

protected ClassLoader(ClassLoader parent) {
 SecurityManager security = System.getSecurityManager();
 if (security != null) {
     security.checkCreateClassLoader();
 }
 // 传入一个父加载器
 // 如果parent=null,那么启动类加载器就是父亲。
 this.parent = parent;
 initialized = true;
}
 
// 双亲委派加载的实现
public Class<?> loadClass(String name) throws ClassNotFoundException {
 return loadClass(name, false);
}

protected synchronized Class<?> loadClass(String name, boolean resolve)
 throws ClassNotFoundException {
 // 先检查该类是否已经被装载过
 Class c = findLoadedClass(name);
 if (c == null) {
     try {
   // 向父加载器委托(加载不到抛ClassNotFoundException)
   if (parent != null) {
       c = parent.loadClass(name, false);
      
      // 最终到启动类加载器(加载不到抛ClassNotFoundException)
   } else {
       c = findBootstrapClass0(name);
   }
     } catch (ClassNotFoundException e) {
         // 父加载器加载不到,调用我们自己设定的findClass(name)进行查找
         // 对于API提供的ClassLoader,findClass()是直接抛ClassNotFoundException
         c = findClass(name);
     }
 }
 // 是否要解析(解析符号引用为直接地址引用)
 // 一般我们用false。
 // 我的理解是使用false的话,程序启动速度应该会有一点点提升,但是第一次执行的时候应该会慢一点点。
 // 当然,这个我们人是感觉不出来的。
 if (resolve) {
     resolveClass(c);
 }
 return c;
}



=====
from
http://blog.sina.com.cn/s/blog_667ac0360102e8ii.html

posted on 2013-01-13 09:29 DolveVita 阅读(121) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2013年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜