显示标签为“Java”的博文。显示所有博文
显示标签为“Java”的博文。显示所有博文

2008年1月9日星期三

(Java) Toolkit修改标题栏图标和鼠标指针图标

Toolkit是个非常有用类的,提供许多修改窗口默认行为的方法。
 
使用Toolkit更改Java应用程序标题栏默认图标:
Toolkit tk=Toolkit.getDefaultToolkit();
Image image=tk.createImage("image.gif"); /*image.gif是你的图标*/
this.setIconImage(image);
 
把默认的鼠标图标改成指定的图标:
Toolkit tk=Toolkit.getDefaultToolkit();
Image img=tk.getImage("mouse.gif"); /*mouse.gif是你的图标*/
Cursor cu=tk.createCustomCursor(img,new Point(10,10),"stick");
this.setCursor(cu);
 

2008年1月5日星期六

(Java小常识) 常量前置的优点

在许多代码中都能见到比较对象/变量是否为空,代码如下:
if (obj   !=   null)
        ...
但是常常我们可以看到这样的代码:
if (null   !=   obj)
        ...
把null写在前面有什么样的好处呢?
这个习惯是这样来的。最早学C编程的时候,像if(a=b)这样的条件是编译通过的,尽管你的意思是if(a==b)。
为了避免出现这种低级错误,写判断的时候习惯把常量写在前边,因为即使出现了if(null=a)这样的错误,也会被编译器提示错误,因为你不能给常量再赋值。
 
 
另外,我们知道equals方法判断的时候把常量放在前面可以防止空指针异常:
if ("".equals(obj))


 

2007年6月11日星期一

(java) Overriding, Overloading

看《Java编程思想》第2版第297页为所有返回类型各写一个类/接口,突然想到能不能仅仅写一个类/接口,通过多态特性,让它自动返回相应的类型呢,尝试失败。

package org.xianyun.j2se.override;
public class Father {
    public String fun(){
        return "string";
    }
}

package org.xianyun.j2se.override;
public class Children extends Father {
    public void fun(){
        // I : 父类返回String,子类返回void。Eclipse报错:返回类型与 Father.fun() 不兼容。
    }
    public void fun(String str){
        // II : 这里是重写(overloading)。
    }
    public String fun(){         // III : Eclipse报错:存在重复的方法 fun()
return "";
    }
}
从 I 处可以看出,系统判断覆写(Overriding)的凭据是方法名和传入参数。如果是覆写,则判断返回参数。
II 处,正常,属于重写(Overloading),此时Children类多了void fun(String)方法。
III 处证明,判断是同一个方法的依据是方法名和传入参数,不参照返回参数。
注:代码在sun jdk下尝试结果相同。

借此再温习一下覆写和重写:
Overriding (覆写)
方法与父类方法同名同参同返回。,即同方法名,同传入参数,同返回参数类型。

Overloading (重载)
方法与父类方法同名,不同传入参数(个数或/和类型),同/不同返回参数类型。





另,在网络技术交流群小学一招,使桌面上图标文本的默认阴影消失:
我的电脑 -> 属性 -> 高级 -> 性能 -> 设置 选中"在桌面上为图标标签使用阴影"。

2007年6月1日星期五

Resin:JDK版本问题

最初将Resin注册为Windows服务时,JDK版本是1.4.2,一直运行正常。

后来装了JavaEE SDK 1.5,发现Resin运行JSP程序时,总是出现"com/sun/tools/javac/Main (Unsupported major.minor version 49.0)"错误信息,甚至resin-doc(.xtp)都无法正常编译运行。上网一查,了解到是版本问题。

我遇到的问题与Resin无法启动类似,但是我用了不同的方法解决。

很简单,不需要任何重装(当然,注册Resin为Windows服务例外)。

1. 在path中设置好需要的JDK版本。
2. 进入命令行模式,cd到Resin安装目录。
3. 运行如下命令,将Resin Web Server从Windows服务中去除。
> httpd -remove
如果运行正常,继续。
(注:不同的resin版本,httpd可运行程序可能会在不同的子目录。我用的是resin3.0.17 for Windows)
4. 然后运行下面的命令再将Resin注册为Windows服务。
> httpd -install
5. ok。

至于原因,Resin官方网说得很清楚:
If you have moved JDK or Resin manually, you get the error from Resin
because the data Resin once get from the registry and the real location
of the executables doesn't match. Reinstall jdk and, then, reinstall
Resin. That will solve this problem.

事后我有研究了一下注册表,在 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Resin] 中有一个名为"ImagePath"的"可扩充字符串值",值中有一个参数"-java_home "D:\jdk1.5.0""就是设置Resin使用的JDK路径的。( 注意可扩充字符串值导出的并不是字符串,而是十六进制数据,所以导入注册表时需要注意。)

2007年5月14日星期一

(Java) 理解String对象不能改变

一直不理解String对象的值不能改变是什么意思,
String a = "A";
a += "B";
这时s等于"AB",a不是已经改变了吗?
后来才明白,上面的String对象a,改变的不仅仅是a的值,a所引用的String对象也已经改变了。a最初引用的是String实例"A",后来引用的是String实例"AB"。
 
public class Str {
    public static void main(String[] args){
        String a = "A";
        String ai = a;
        a.concat("B"); // I
        a += "C"; // II
        System.out.println(a);
        System.out.println(a == ai);
        System.out.println(a.equals(ai));

        StringBuffer sb = new StringBuffer("SB");
        StringBuffer sbi = sb;
        sb.append("APPEND");
        System.out.println(sb);
        System.out.println(sb == sbi);
        System.out.println(sb.equals(sbi));
    }
}

仅注释掉行 II,结果如下:
A
true
true
SBAPPEND
true
true
此时对象a的值仍为"A",a对对象的引用也没有改变。
 

仅注释掉行 I,结果如下:
AC
false
false
SBAPPEND
true
true
此时对象a的值已经改变,但是a对对象的引用也已经改变。


总结:String对象实例"A"的值是不可改变的,但是变量a对对象的引用可以改变。

2007年2月8日星期四

statement 执行存储过程,获取返回的多个结果

from : http://www.nk975.com/sswater/myref/index.asp?id=18

Java 中,当 statement 执行存储过程或者一次性执行多条语句时,返回多个结果的处理方法:

boolean moreResult = statement.execute(); // 表示结果是 ResultSet
boolean moreUpdate = statement.getUpdateCount() != -1; // 表示结果是 "UPDATE ..." 或者 "INSERT ..." 的结果

while( moreResult moreUpdate )
{
if( moreResult )
{
ResultSet rs = statement.getResultSet();
// ... 相关操作
}
else
{
int count = statement.getUpdateCount();
// ... 得到的结果是更新了多少行,或者插入了多少行,或者删除了多少行等等
}

moreResult = statement.getMoreResults();
moreUpdate = statement.getUpdateCount() != -1;
}

2007年1月27日星期六

(转) RMI一步一步来

http://www.it.com.cn/f/edu/061/4/218911.htm (闲耘转自此,发此文时原文链接暂不可用。)
2006-1-4 9:22:00 文/ zhangxhsj 出处:javafan.net
此文是转帖,闲耘作了稍许修改
 
RMI,远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。

RMI的基础是接口,RMI构架基于一个重要的原理:定义接口和定义接口的具体实现是分开的。下面我们通过具体的例子,建立一个简单的远程计算服务和使用它的客户程序

一个正常工作的RMI系统由下面几个部分组成:
    远程服务的接口定义
    远程服务接口的具体实现
    桩(Stub)和框架(Skeleton)文件
    一个运行远程服务的服务器
    一个RMI命名服务,它允许客户端去发现这个远程服务
    类文件的提供者(一个HTTP或者FTP服务器)
    一个需要这个远程服务的客户端程序
下面我们一步一步建立一个简单的RMI系统。首先在你的机器里建立一个新的文件夹,以便放置我们创建的文件,为了简单起见,我们只使用一个文件夹存放客户端和服务端代码,并且在同一个目录下运行服务端和客户端。

如果所有的RMI文件都已经设计好了,那么你需要下面的几个步骤去生成你的系统:

1、 编写并且编译接口的Java代码
2、 编写并且编译接口实现的Java代码
3、 从接口实现类中生成桩(Stub)和框架(Skeleton)类文件
4、 编写远程服务的主运行程序
5、 编写RMI的客户端程序
6、 安装并且运行RMI系统

1、 接口
第一步就是建立和编译服务接口的Java代码。这个接口定义了所有的提供远程服务的功能,下面是源程序:

//Calculator.java
//define the interface

import java.rmi.Remote;

public interface Calculator extends Remote {
    public long add(long a, long b)
        throws java.rmi.RemoteException;

    public long sub(long a, long b)
        throws java.rmi.RemoteException;

    public long mul(long a, long b)
        throws java.rmi.RemoteException;

    public long div(long a, long b)
        throws java.rmi.RemoteException;
}

注意,这个接口继承自Remote,每一个定义的方法都必须抛出一个RemoteException异常对象。

建立这个文件,把它存放在刚才的目录下,并且编译。

>javac Calculator.java

2、 接口的具体实现

下一步,我们就要写远程服务的具体实现,这是一个CalculatorImpl类文件:

//CalculatorImpl.java
//Implementation

import java.rmi.server.UnicastRemoteObject

public class CalculatorImpl
    extends UnicastRemoteObject
    implements Calculator {

    // 这个实现必须有一个显式的构造函数,
    //并且要抛出一个RemoteException异常

    public CalculatorImpl()
    throws java.rmi.RemoteException {
        super();
    }

    public long add(long a, long b)
        throws java.rmi.RemoteException {
        return a + b;
    }

    public long sub(long a, long b)
        throws java.rmi.RemoteException {
        return a - b;
    }

    public long mul(long a, long b)
        throws java.rmi.RemoteException {
        return a * b;
    }

    public long div(long a, long b)
        throws java.rmi.RemoteException {
        return a / b;
    }
}

同样的,把这个文件保存在你的目录里然后编译他。

这个实现类使用了UnicastRemoteObject去联接RMI系统。在我们的例子中,我们是直接的从UnicastRemoteObject这个类上继承的,事实上并不一定要这样做,如果一个类不是从UnicastRmeoteObject上继承,那必须使用它的exportObject()方法去联接到RMI。

如果一个类继承自UnicastRemoteObject,那么它必须提供一个构造函数并且声明抛出一个RemoteException对象。当这个构造函数调用了super(),它久激活UnicastRemoteObject中的代码完成RMI的连接和远程对象的初始化。

3、 桩(Stubs)和框架(Skeletons)

下一步就是要使用RMI编译器rmic来生成桩和框架文件,这个编译运行在远程服务实现类文件上。

>rmic CalculatorImpl

在你的目录下运行上面的命令,成功执行完上面的命令你可以发现一个Calculator_stub.class文件,如果你是使用的Java2SDK,那么你还可以发现Calculator_Skel.class文件。


4、 主机服务器

远程RMI服务必须是在一个服务器中运行的。CalculatorServer类是一个非常简单的服务器。

//CalculatorServer.java
import java.rmi.Naming;

public class CalculatorServer {
    public CalculatorServer() {
        try {
            Calculator c = new CalculatorImpl();
            Naming.rebind("rmi://localhost:1099/CalculatorService", c);
        } catch (Exception e) {
            System .out.println("Trouble: " + e);
        }
    }

    public static void main(String args[]) {
        new CalculatorServer();
    }
}

建立这个服务器程序,然后保存到你的目录下,并且编译它。

5、 客户端

客户端源代码如下:

//CalculatorClient.java

import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;

public class CalculatorClient {
    public static void main(String[] args) {
        try {
            Calculator c = (Calculator)
                Naming.lookup("rmi://localhost/CalculatorService");
            System.out.println( c.sub(4, 3) );
            System.out.println( c.add(4, 5) );
            System.out.println( c.mul(3, 6) );
            System.out.println( c.div(9, 3) );
        } catch (MalformedURLException murle) {
            System.out.println();
            System.out.println("MalformedURLException");
            System.out.println(murle);
        } catch (RemoteException re) {
            System.out.println();
            System .out.println("RemoteException");
            System.out.println(re);
        } catch (NotBoundException nbe) {
            System.out.println();
            System.out.println("NotBoundException");
            System.out.println(nbe);
        } catch (java.lang.ArithmeticException ae) {
            System.out.println();
            System.out.println("java.lang.ArithmeticException");
            System.out.println(ae);
        }
    }
}

保存这个客户端程序到你的目录下(注意这个目录是一开始建立那个,所有的我们的文件都在那个目录下),并且编译他。

6、 运行RMI系统

现在我们建立了所有运行这个简单RMI系统所需的文件,现在我们终于可以运行这个RMI系统啦!来享受吧。

我们是在命令控制台下运行这个系统的,你必须开启三个控制台窗口,一个运行服务器,一个运行客户端,还有一个运行RMIRegistry。

首先运行注册程序RMIRegistry,你必须在包含你刚写的类的那么目录下运行这个注册程序。

>rmiregistry

好,这个命令成功的话,注册程序已经开始运行了,不要管他,现在切换到另外一个控制台,在第二个控制台里,我们运行服务器CalculatorService,因为RMI的安全机制将在服务端发生作用,所以你必须增加一条安全策略。以下是对应安全策略的例子 policy.txt :

grant {
    permission java.security.AllPermission "", "";
};

注意:这是一条最简单的安全策略,它允许任何人做任何事,对于你的更加关键性的应用,你必须指定更加详细安全策略。
现在为了运行服务端,你需要除客户类(CalculatorClient.class)之外的所有的类文件。确认安全策略在policy.txt文件之后,使用如下命令来运行服务器。

> java -Djava.security.policy=policy.txt CalculatorServer

这个服务器就开始工作了,把接口的实现加载到内存等待客户端的联接。好现在切换到第三个控制台,启动我们的客户端。
为了在其他的机器运行客户端程序你需要一个远程接口(Calculator.class) 和一个stub(CalculatorImpl_Stub.class)。 使用如下命令运行客户端

 prompt> java -Djava.security.policy=policy.txt CalculatorClient

如果所有的这些都成功运行,你应该看到下面的输出:

1
9
18
3

如果你看到了上面的输出,恭喜你,你成功了,你已经成功的创建了一个RMI系统,并且使他正确工作了。即使你运行在同一个计算机上,RMI还是使用了你的网络堆栈和TCP/IP去进行通讯,并且是运行在三个不同的Java虚拟机上。这已经是一个完整的RMI系统。
 
 
--
闲耘注,我测试了不用 -Djava.security.policy=policy.txt 参数也执行成功,可能是我本机权限足够...

2007年1月20日星期六

AnimalFarm

 
George Wrwell在Animal Farm中说过:"所有的动物都是平等的." 看看下面的东西,你就知道是否是这样的了?

public class AnimalFarm{
    public static void main(String[] args){
        final String pig = "length: 10";
        final String dog = "length: " + pig.length();
        System.out.println("Animals are equal:" +
            pig == dog);
    }
}
 
(代码清单一)
 
初一看该程序,你可能认为它会打印Animal are equal: true.毕竟,pig和dog都是final的string类型变量,而且它们都被初始化为字符序列"length:10".

然而当我们运行程序来验证一下,它是什么呢?结果为:false,并没有打印其他的东西.它没有打印Animal are equal: . 它怎么会不打印这个字符串呢?

 

我把代码进行增补如下:
 
public class AnimalFarm{
    public static void main(String[] args){
        final String pig = "length: 10";
        final String dog = "length: " + pig.length();
        System.out.println("Animals length are equal:" + (pig.length() == dog.length()));
        System.out.println("Animals are equal:" + pig. equals(dog));
        System.out.println("Animals are equal(=):" + (pig == dog));
        System.out.println("Animals are equal(=):" + pig == dog);
        System.out.print("Animals are equal:");
        System.out.println(pig == dog);
    }
}
 
(代码清单二)
 
测试运行:
 
Animals length are equal:true
Animals are equal:true
Animals are equal(=):false
false
Animals are equal:false
 
 
您是否已经发现了结果了呢,我结论是,运算符的优先级造成了这样有意思的影响。
 
因为boolean类型运算符的运算优先级是比较低的,代码行
System.out.println("Animals are equal(=):" + pig == dog);
中先进行字符串连接运算:"Animals are equal(=):" + pig
然后进行字符串间的比较,而"Animals are equal(=):" + pig是不等于dog的
所以最后仅仅输出了false
 
如果代码清单二中代码行
System.out.println("Animals length are equal:" + (pig.length() == dog.length()));
中后面的两个字符串长度比较没有使用括号
则会出现异常
AnimalFarm.java:5: operator == cannot be applied to java.lang.String,int
        System.out.println("Animals length are equal:" + pig.length() == dog.length());
这个异常也说明了上面理解的正确性。
 
 
似乎在一个关于Java怪题(忘记书名)的书上见过类似问题,不知道是否记错了。
 
 

关于myeclipse5.1下载地址和注册码机的源代码


下载myeclipse5.1的话需要去myeclipse的官方网站,共有100多M之大, 点击这里进入下载 (进入官方网站后点download area,注册一个用户进行下载,如果你的确下不了,也可留言给我,我发给你。),下在完成后接下来就是注册了。

如果你之前是用过myeclise3.2之类的话就无需再注册,新安装完成后就原来的注册仍然有效。如果你是新安装的话就需注册了, 你可以使用以前的myeclise3.2的注册机来注册,算法并没有改变,如果你要找3.x的注册机的话,用不着了。下面我贴出注册机的java源代码,直接运行此class就能生成注册码并可成功注册。

注册机源代码如下:

 
public class Main {
    private static final String L = "Decompiling this copyrighted software is a violation of both your license agreement and the Digital Millenium Copyright Act of 1998 ( http://www.loc.gov/copyright/legislation/dmca.pdf). Under section 1204 of the DMCA, penalties range up to a $500,000 fine or up to five years imprisonment for a first offense. Think about it; pay for a license, avoid prosecution, and feel better about yourself.";

    public static void main(String[] args) {
        String userId = "xianyun";
         // MyEclipse4.1 GA
         // 其中491(4.9.1)/400(4.0)/401(4.1)/501(5.1.0),()内为版本号,9912310代表注册码过期时间2099/12/31
         String need = userId.substring(0, 1) + "YE3MP-401-00-9912310";
         // MyEclipse4.0.0 GA
         // String need = userId.substring(0,1) + "YE3MP-400-01-9912310";
         // MyEclipse4.9.1
         // String need = userId.substring(0,1) + "YE3MP-491-01-9912310";
         // MyEclipse5.1.0 GA
         // String need = userId.substring(0,1) + "YE3MP-501-00-9912310";
         String dx = need + L + userId;
         int suf = decode(dx);
         // System.out.println("SUF:"+suf);
         String code = need + suf;
         System .out.println(change(code));
    }

    static int decode(String s) {
        int i = 0;
        char ac[] = s.toCharArray();
        int j = 0;
        for (int k = ac.length; j < k; j++) {
            i = 31 * i + ac[j];
        }
        return Math.abs(i);
        }

    static String change(String s) {
        byte abyte0[] = s.getBytes();
        char ac[] = new char[s.length()];
        int i = 0;
        for (int k = abyte0.length; i < k; i++) {
            int j = abyte0[i];
            if (j >= 48 && j <= 57)
                j = ((j - 48) + 5) % 10 + 48;
            else if (j >= 65 && j <= 90)
                j = ((j - 65) + 13) % 26 + 65;
            else if (j >= 97 && j <= 122)
                j = ((j - 97) + 13) % 26 + 97;
            ac[i] = (char) j;
        }
        return String.valueOf(ac);
     }
}