2013年1月13日

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 @ 2013-01-13 09:29 DolveVita 阅读(121) | 评论 (0)编辑 收藏

Java的SystemTray类的使用方法

Java的SystemTray类的使用方法

JDK1.6版增加了java.awt.SystemTray类,该类表示桌面的系统托盘,这对大多数系统托盘应用已经足够。如果这个类还是不能满足您的需求,可以试一试JDIC (JDesktop Integration Components)。
JDK1.6的API文档,给出了这个类的用法。有人愿意把创建系统托盘的代码直接放在主应用代码中,笔者更倾向于把创建系统托盘的责任分派给一个单独的类,这符合类的设计原则。在主应用中直接调用该类的工厂方法就可以了,结构清晰,便于维护,改动或增加系统托盘的功能,不必改动主应用代码。
创建系统托盘的类(TrayFactory.java)的代码如下:

//package com.jnmc.liang.systemtray;

import java.awt.*;
import java.awt.event.*;

public class TrayFactory {
        private TrayIcon trayIcon = null;
        private Component comp = null;
        private String trayImageName = null;
        private String tooltip = null;
        
        private TrayFactory(Component comp, String trayImageName, String tooltip) {
                this.comp = comp;
                this.trayImageName = trayImageName;
                this.tooltip = tooltip;
                
                init();
        }
        
        private void init() {
                if (SystemTray.isSupported()) {
                        SystemTray tray = SystemTray.getSystemTray();
                        Image image  = Toolkit.getDefaultToolkit().getImage(trayImageName);
                        PopupMenu popupMenu = new PopupMenu();
                        MenuItem restoreItem = new MenuItem("还原"); 
                        MenuItem exitItem  = new MenuItem("退出");
                        
                        restoreItem.addActionListener(new RestoreItemActionListener());                        
                        exitItem.addActionListener(new ExitItemActionListener());
                        
                        popupMenu.add(restoreItem);
                        popupMenu.addSeparator();
                        popupMenu.add(exitItem);
                        
                        trayIcon = new TrayIcon(image, tooltip,  popupMenu);
                        trayIcon.addMouseListener(new TrayIconMouseListener());
                        //trayIcon.addActionListener(new TrayIconActionListener());
                                                
                        try {
                                tray.add(trayIcon);
                        }
                        catch (AWTException e) {
                                System.err.println(e);
                        }
                }
                else {
                        //..........
                }
        }

        private class RestoreItemActionListener implements ActionListener {
                public void actionPerformed(ActionEvent ae) {
                        comp.setVisible(true);
                }
        }
                
        private class ExitItemActionListener implements ActionListener {
                public void actionPerformed(ActionEvent ae) {
                        System.exit(0);
                }
        }
        
        private class TrayIconMouseListener extends MouseAdapter {
                public void mousePressed(MouseEvent me) {
                        if (me.getButton() == MouseEvent.BUTTON1) {
                                comp.setVisible(true);
                        }
                }
        }

        public static void createTray(Component comp, String trayImageName, String tooltip) {
                new TrayFactory(comp, trayImageName, tooltip);
        }
}

这个类的构造方法是private的,因为创建该类的实例不是我们的目的,另一方面是为了方便系统托盘的创建。
构造方法有3个参数:
第1个参数是一个Component,这就是您所要显示或隐藏的主窗体。当然,您把这个参数写成Component的子类也无妨,这里是为了增加类的通用性。
第2个参数是一个String,它是一个image文件的名称,将来用这个文件创建托盘图标TrayIcon。
第3个参数也是一个String,它是工具提示字符串,当您把鼠标放到托盘图标上的时候,托盘图标将弹出这个字符串的内容。
创建系统托盘的具体代码在方法private void init()中。
创建系统托盘的任务分为两个步骤:
首先创建托盘图标(TrayIcon),其次把托盘图标添加到系统托盘(SystemTray)中。
Java.awt.TrayIcon提供3种构造方法创建TrayIcon实例,这里采用第三种构造方法:
                trayIcon = new TrayIcon(image, tooltip,  popupMenu);
其中,image对象由TrayFactory类构造方法的第二个参数trayImageName创建:
Image image  = Toolkit.getDefaultToolkit().getImage(trayImageName);
tooltip就是TrayFactory类构造方法的第三个参数
由于不能朝前引用,PopupMenu对象popupMenu必须在创建trayIcon对象之前创建,并给popup菜单项添加动作监听器来处理菜单项的动作(点击)事件,由于处理动作事件比较简单,这里不做具体分析,只对TrayIcon的鼠标事件做出说明。
我们希望在托盘图标上按下鼠标左键时显示主窗体,所以必须处理托盘图标的鼠标按下事件。我们用TrayIconMouseListener私有内部类(private inner class)来处理鼠标按下事件。不论按下鼠标左键还是右键,都会产生鼠标事件,都会引起mousePressed方法的调用,所以在这个方法中只处理左键而忽略右键,把右键留给popup菜单:
                        if (me.getButton() == MouseEvent.BUTTON1) {
                                comp.setVisible(true);
                        }
这时,就可以给init()方法中创建的TrayIcon对象trayIcon添加鼠标监听器了:
trayIcon.addMouseListener(new TrayIconMouseListener());
利用TrayFactory类对主应用创建系统托盘时,只需在主应用中调用该类的工厂方法即可:
TrayFactory.createTray(comp, trayImageName, tooltip);
注意这一句,一定要放在适当的位置:主应用从开始启动到启动完毕,必须有机会执行这一句。所以建议把这一句放在主应用的构造方法中,或者干脆放在显示主窗体的前一个语句的位置:

//其他语句
               JFrame mainFrame = new JFrame("测试主窗体");
                mainFrame.getContentPane().add(otherVisibleObj, BorderLayout.CENTER);
                mainFrame.pack();
                TrayFactory.createTray(mainFrame, "images/icon.png", "这是工具提示");        
                mainFrame.setVisible(true);
下面给出一个完整的例子。
主应用(MainApp.java)源代码如下:

import java.awt.*;
import javax.swing.*;

public class MainApp {
        private static void createAndShowGUI() {
                JFrame mainFrame = new JFrame("测试主窗体");
                JLabel jLabel = new JLabel("这是一个标签", SwingConstants.CENTER);
                jLabel.setPreferredSize(new Dimension(400, 300));
    mainFrame.getContentPane().add(jLabel, BorderLayout.CENTER);
    
                mainFrame.pack();
                TrayFactory.createTray(mainFrame, "images/icon.png", "你好,Java!\nHello,Java!");
                mainFrame.setVisible(true);
        }
    
        public static void main(String[] args) {
                String lf = UIManager.getSystemLookAndFeelClassName();
                try {
                        UIManager.setLookAndFeel(lf);
                } 
                catch(Exception e) {
                }
                
                javax.swing.SwingUtilities.invokeLater(new Runnable() {
                                public void run() {
                                        createAndShowGUI();
                                }
    });
           
}

为简单起见,可以把TrayFactory.java和MainApp.java放在同一目录下,把icon.png文件放在当前目录的images目录下。

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

posted @ 2013-01-13 09:27 DolveVita 阅读(255) | 评论 (0)编辑 收藏

<2013年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜