十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
//这是个聊天晌没掘程序, 在ECLIPSE 运行 Client.java 就宴核可以了。 连接是:localhost
成都网站建设哪家好,找创新互联!专注于网页设计、成都网站建设公司、微信开发、小程序开发、集团成都企业网站定制等服务项目。核心团队均拥有互联网行业多年经验,服务众多知名企业客户;涵盖的客户类型包括:成都垃圾桶等众多领域,积累了大量丰富的经验,同时也获得了客户的一致称赞!
//Server 代码,
package message;
import java.io.*;
import java点虐 .*;
import java.util.*;
public class Server {
public static void main(String[] args) throws Exception{
System.out.print("Server");
ServerSocket socket=new ServerSocket(8888);
Vector v=new Vector();
while(true){
Socket sk=socket.accept();
DataInputStream in=new DataInputStream(sk.getInputStream());
DataOutputStream out=new DataOutputStream(sk.getOutputStream());
v.add(sk);
new ServerThread(in,v).start();
}
}
}
//ServerThread.java 代码
package message;
import java点虐 .*;
import java.io.*;
import java.util.*;
public class ServerThread extends Thread{
DataInputStream in;
Vector all;
public ServerThread(DataInputStream in,Vector v){
this.in=in;
this.all=v;
}
public void run()
{
while(true)
{
try{
String s1=in.readUTF();
for(int i=0;iall.size();i++)
{
Object obj=all.get(i);
Socket socket=(Socket)obj;
DataOutputStream out=new DataOutputStream(socket.getOutputStream());
out.writeUTF(s1);
System.out.print(i);
out.flush();
}
System.out.print("Message send over!");
}catch(Exception e){e.printStackTrace();};
}
}
}
//ClientFrame.java 代码
package message;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java点虐 .*;
import java.io.*;
public class ClientFrame extends JFrame implements ActionListener{
JButton b1=new JButton ("SendMessage");
JButton b2=new JButton("Link Server");
JTextField t1=new JTextField(20);
JTextField t2=new JTextField(20);
JLabel l=new JLabel("输入服务器名察迹字:");
JTextArea area=new JTextArea(10,20);
JPanel p1=new JPanel();
JPanel p2=new JPanel();
JPanel p3=new JPanel();
JPanel p4=new JPanel();
Socket socket;
public ClientFrame()
{
this.getContentPane().add(p1);
p2.add(new JScrollPane(area));
p3.add(t1);
p3.add(b1);
p4.add(l);
p4.add(t2);
p4.add(b2);
p2.setLayout(new FlowLayout());
p3.setLayout(new FlowLayout());
p4.setLayout(new FlowLayout());
p1.setLayout(new BorderLayout());
p1.add("North",p2);
p1.add("Center",p3);
p1.add("South",p4);
b1.addActionListener(this);
b2.addActionListener(this);
this.pack();
show();
}
public void actionPerformed(ActionEvent e)
{
if(e.getActionCommand().equals("Link Server"))
{
try{
socket=new Socket(t2.getText(),8888);
b2.setEnabled(false);
JOptionPane.showMessageDialog(this, "Connection Success");
DataInputStream in=new DataInputStream(socket.getInputStream());
new ClientThread(in,area).start();
}
catch(Exception e1){
JOptionPane.showMessageDialog(this, "Connection Error");
e1.printStackTrace();};
}
else if(e.getActionCommand().equals("SendMessage"))
{
try{
DataOutputStream out=new DataOutputStream(socket.getOutputStream());
out.writeUTF(t1.getText());
t1.setText("");
}catch(Exception e1){e1.printStackTrace();};
}
}
}
//ClientThread.java 代码
package message;
import java点虐 .*;
import java.io.*;
import javax.swing.*;
public class ClientThread extends Thread {
DataInputStream in;
JTextArea area;
public ClientThread(DataInputStream in,JTextArea area){
this.in=in;
this.area=area;
}
public void run()
{
while(true){
try{
String s=in.readUTF();
area.append(s);
}
catch(Exception e){e.printStackTrace();};
}
}
}
//Client.java代码
package message;
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
new ClientFrame();
}
}
// 每段代码都是个类,不要弄在一个文件里。 运行 Client.java
good luck to you!
区塌链做别就是代码段第一个花括号的位置嘛.
第一种是JAVA官唤氏方的标准代码格式团衡,用Eclipse格式化代码默认会格式化成这样
第二种是C/C++/C#的习惯,写Java代码的时候不建议用
俄罗斯方块——java源燃圆代码提供
import java.awt.*;
import java.awt.event.*;
//俄罗斯方块类
public class ERS_Block extends Frame{
public static boolean isPlay=false;
public static int level=1,score=0;
public static TextField scoreField,levelField;
public static MyTimer timer;
GameCanvas gameScr;
public static void main(String[] argus){
ERS_Block ers = new ERS_Block("俄罗斯方块游戏 V1.0 Author:Vincent");
WindowListener win_listener = new WinListener();
ers.addWindowListener(win_listener);
}
//俄罗斯方块类的构造方法
ERS_Block(String title){
super(title);
setSize(600,480);
setLayout(new GridLayout(1,2));
gameScr = new GameCanvas();
gameScr.addKeyListener(gameScr);
timer = new MyTimer(gameScr);
timer.setDaemon(true);
timer.start();
timer.suspend();
add(gameScr);
Panel rightScr = new Panel();
rightScr.setLayout(new GridLayout(2,1,0,30));
rightScr.setSize(120,500);
add(rightScr);
//右边信息窗体的布局
MyPanel infoScr = new MyPanel();
infoScr.setLayout(new GridLayout(4,1,0,5));
infoScr.setSize(120,300);
rightScr.add(infoScr);
//定义标签和初始值
Label scorep = new Label("薯锋分皮手塌数:",Label.LEFT);
Label levelp = new Label("级数:",Label.LEFT);
scoreField = new TextField(8);
levelField = new TextField(8);
scoreField.setEditable(false);
levelField.setEditable(false);
infoScr.add(scorep);
infoScr.add(scoreField);
infoScr.add(levelp);
infoScr.add(levelField);
scorep.setSize(new Dimension(20,60));
scoreField.setSize(new Dimension(20,60));
levelp.setSize(new Dimension(20,60));
levelField.setSize(new Dimension(20,60));
scoreField.setText("0");
levelField.setText("1");
//右边控制按钮窗体的布局
MyPanel controlScr = new MyPanel();
controlScr.setLayout(new GridLayout(5,1,0,5));
rightScr.add(controlScr);
//定义按钮play
Button play_b = new Button("开始游戏");
play_b.setSize(new Dimension(50,200));
play_b.addActionListener(new Command(Command.button_play,gameScr));
//定义按钮Level UP
Button level_up_b = new Button("提高级数");
level_up_b.setSize(new Dimension(50,200));
level_up_b.addActionListener(new Command(Command.button_levelup,gameScr));
//定义按钮Level Down
Button level_down_b =new Button("降低级数");
level_down_b.setSize(new Dimension(50,200));
level_down_b.addActionListener(new Command(Command.button_leveldown,gameScr));
//定义按钮Level Pause
Button pause_b =new Button("游戏暂停");
pause_b.setSize(new Dimension(50,200));
pause_b.addActionListener(new Command(Command.button_pause,gameScr));
//定义按钮Quit
Button quit_b = new Button("退出游戏");
quit_b.setSize(new Dimension(50,200));
quit_b.addActionListener(new Command(Command.button_quit,gameScr));
controlScr.add(play_b);
controlScr.add(level_up_b);
controlScr.add(level_down_b);
controlScr.add(pause_b);
controlScr.add(quit_b);
setVisible(true);
gameScr.requestFocus();
}
}
//重写MyPanel类,使Panel的四周留空间
class MyPanel extends Panel{
public Insets getInsets(){
return new Insets(30,50,30,50);
}
}
//游戏画布类
class GameCanvas extends Canvas implements KeyListener{
final int unitSize = 30; //小方块边长
int rowNum; //正方格的行数
int columnNum; //正方格的列数
int maxAllowRowNum; //允许有多少行未削
int blockInitRow; //新出现块的起始行坐标
int blockInitCol; //新出现块的起始列坐标
int [][] scrArr; //屏幕数组
Block b; //对方快的引用
//画布类的构造方法
GameCanvas(){
rowNum = 15;
columnNum = 10;
maxAllowRowNum = rowNum - 2;
b = new Block(this);
blockInitRow = rowNum - 1;
blockInitCol = columnNum/2 - 2;
scrArr = new int [32][32];
}
//初始化屏幕,并将屏幕数组清零的方法
void initScr(){
for(int i=0;irowNum;i++)
for (int j=0; jcolumnNum;j++)
scrArr[j]=0;
b.reset();
repaint();
}
//重新刷新画布方法
public void paint(Graphics g){
for(int i = 0; i rowNum; i++)
for(int j = 0; j columnNum; j++)
drawUnit(i,j,scrArr[j]);
}
//画方块的方法
public void drawUnit(int row,int col,int type){
scrArr[row][col] = type;
Graphics g = getGraphics();
tch(type){ //表示画方快的方法
case 0: g.setColor(Color.black);break; //以背景为颜色画
case 1: g.setColor(Color.blue);break; //画正在下落的方块
case 2: g.setColor(Color.magenta);break; //画已经落下的方法
}
g.fill3DRect(col*unitSize,getSize().height-(row+1)*unitSize,unitSize,unitSize,true);
g.dispose();
}
public Block getBlock(){
return b; //返回block实例的引用
}
//返回屏幕数组中(row,col)位置的属性值
public int getScrArrXY(int row,int col){
if (row 0 || row = rowNum || col 0 || col = columnNum)
return(-1);
else
return(scrArr[row][col]);
}
//返回新块的初始行坐标方法
public int getInitRow(){
return(blockInitRow); //返回新块的初始行坐标
}
//返回新块的初始列坐标方法
public int getInitCol(){
return(blockInitCol); //返回新块的初始列坐标
}
//满行删除方法
void deleteFullLine(){
int full_line_num = 0;
int k = 0;
for (int i=0;irowNum;i++){
boolean isfull = true;
L1:for(int j=0;jcolumnNum;j++)
if(scrArr[j] == 0){
k++;
isfull = false;
break L1;
}
if(isfull) full_line_num++;
if(k!=0 k-1!=i !isfull)
for(int j = 0; j columnNum; j++){
if (scrArr[j] == 0)
drawUnit(k-1,j,0);
else
drawUnit(k-1,j,2);
scrArr[k-1][j] = scrArr[j];
}
}
for(int i = k-1 ;i rowNum; i++){
for(int j = 0; j columnNum; j++){
drawUnit(i,j,0);
scrArr[j]=0;
}
}
ERS_Block.score += full_line_num;
ERS_Block.scoreField.setText(""+ERS_Block.score);
}
//判断游戏是否结束方法
boolean isGameEnd(){
for (int col = 0 ; col columnNum; col ++){
if(scrArr[maxAllowRowNum][col] !=0)
return true;
}
return false;
}
public void keyTyped(KeyEvent e){
}
public void keyReleased(KeyEvent e){
}
//处理键盘输入的方法
public void keyPressed(KeyEvent e){
if(!ERS_Block.isPlay)
return;
tch(e.getKeyCode()){
case KeyEvent.VK_DOWN:b.fallDown();break;
case KeyEvent.VK_LEFT:b.leftMove();break;
case KeyEvent.VK_RIGHT:b.rightMove();break;
case KeyEvent.VK_SPACE:b.leftTurn();break;
}
}
}
//处理控制类
class Command implements ActionListener{
static final int button_play = 1; //给按钮分配编号
static final int button_levelup = 2;
static final int button_leveldown = 3;
static final int button_quit = 4;
static final int button_pause = 5;
static boolean pause_resume = true;
int curButton; //当前按钮
GameCanvas scr;
//控制按钮类的构造方法
Command(int button,GameCanvas scr){
curButton = button;
this.scr=scr;
}
//按钮执行方法
public void actionPerformed (ActionEvent e){
tch(curButton){
case button_play:if(!ERS_Block.isPlay){
scr.initScr();
ERS_Block.isPlay = true;
ERS_Block.score = 0;
ERS_Block.scoreField.setText("0");
ERS_Block.timer.resume();
}
scr.requestFocus();
break;
case button_levelup:if(ERS_Block.level 10){
ERS_Block.level++;
ERS_Block.levelField.setText(""+ERS_Block.level);
ERS_Block.score = 0;
ERS_Block.scoreField.setText(""+ERS_Block.score);
}
scr.requestFocus();
break;
case button_leveldown:if(ERS_Block.level 1){
ERS_Block.level--;
ERS_Block.levelField.setText(""+ERS_Block.level);
ERS_Block.score = 0;
ERS_Block.scoreField.setText(""+ERS_Block.score);
}
scr.requestFocus();
break;
case button_pause:if(pause_resume){
ERS_Block.timer.suspend();
pause_resume = false;
}else{
ERS_Block.timer.resume();
pause_resume = true;
}
scr.requestFocus();
break;
case button_quit:System.exit(0);
}
}
}
//方块类
class Block {
static int[][] pattern = {
{0x0f00,0x4444,0x0f00,0x4444},//用十六进至表示,本行表示长条四种状态
{0x04e0,0x0464,0x00e4,0x04c4},
{0x4620,0x6c00,0x4620,0x6c00},
{0x2640,0xc600,0x2640,0xc600},
{0x6220,0x1700,0x2230,0x0740},
{0x6440,0x0e20,0x44c0,0x8e00},
{0x0660,0x0660,0x0660,0x0660}
};
int blockType; //块的模式号(0-6)
int turnState; //块的翻转状态(0-3)
int blockState; //快的下落状态
int row,col; //块在画布上的坐标
GameCanvas scr;
//块类的构造方法
Block(GameCanvas scr){
this.scr = scr;
blockType = (int)(Math.random() * 1000)%7;
turnState = (int)(Math.random() * 1000)%4;
blockState = 1;
row = scr.getInitRow();
col = scr.getInitCol();
}
//重新初始化块,并显示新块
public void reset(){
blockType = (int)(Math.random() * 1000)%7;
turnState = (int)(Math.random() * 1000)%4;
blockState = 1;
row = scr.getInitRow();
col = scr.getInitCol();
dispBlock(1);
}
//实现“块”翻转的方法
public void leftTurn(){
if(assertValid(blockType,(turnState + 1)%4,row,col)){
dispBlock(0);
turnState = (turnState + 1)%4;
dispBlock(1);
}
}
//实现“块”的左移的方法
public void leftMove(){
if(assertValid(blockType,turnState,row,col-1)){
dispBlock(0);
col--;
dispBlock(1);
}
}
//实现块的右移
public void rightMove(){
if(assertValid(blockType,turnState,row,col+1)){
dispBlock(0);
col++;
dispBlock(1);
}
}
//实现块落下的操作的方法
public boolean fallDown(){
if(blockState == 2)
return(false);
if(assertValid(blockType,turnState,row-1,col)){
dispBlock(0);
row--;
dispBlock(1);
return(true);
}else{
blockState = 2;
dispBlock(2);
return(false);
}
}
//判断是否正确的方法
boolean assertValid(int t,int s,int row,int col){
int k = 0x8000;
for(int i = 0; i 4; i++){
for(int j = 0; j 4; j++){
if((int)(pattern[t][s]k) != 0){
int temp = scr.getScrArrXY(row-i,col+j);
if (temp0||temp==2)
return false;
}
k = k 1;
}
}
return true;
}
//同步显示的方法
public synchronized void dispBlock(int s){
int k = 0x8000;
for (int i = 0; i 4; i++){
for(int j = 0; j 4; j++){
if(((int)pattern[blockType][turnState]k) != 0){
scr.drawUnit(row-i,col+j,s);
}
k=k1;
}
}
}
}
//定时线程
class MyTimer extends Thread{
GameCanvas scr;
public MyTimer(GameCanvas scr){
this.scr = scr;
}
public void run(){
while(true){
try{
sleep((10-ERS_Block.level + 1)*100);
}
catch(InterruptedException e){}
if(!scr.getBlock().fallDown()){
scr.deleteFullLine();
if(scr.isGameEnd()){
ERS_Block.isPlay = false;
suspend();
}else
scr.getBlock().reset();
}
}
}
}
class WinListener extends WindowAdapter{
public void windowClosing (WindowEvent l){
System.exit(0);
}
}
下文来自CSDNOracle对Sun的收购引发了人们对Java未来的一丝担心,Oracle能否继续保持Java的开放性,面对Ruby、Python或PHP 等一批轻量型语言的崛起,Java能否继续保持其在开发领域的领导地位?14年前,Sun公司的一位营销天才把一门试验枣宴改性的跨平台语言由象征踏实的Oak(橡树),改名为香气四溢的Java(咖啡)时,可能他没有想到这 门语言能有后来的辉煌。事实上,如果现在Sun想为这门语言改名,以准确体现其在计算机行业的地位,似乎Oak更形象。今天,虽然Java语言并非真正意 义上的遍地开花,但它已经出现在众多场合和设备中,而且它享有运行稳定、设计精良的美名; Java代码也许无法主导所有计算机或所有平台,但它离成为通用语言已近在咫尺。Java之父詹姆斯戈斯林(James Gosling)在Oracle主办的OpenWorld大会上登台发言时阐述了这一点。他调出JavaFX幻灯片,上面是一连串统计数字:超过8.5亿 个具有Java功能的桌面机和大约100亿个具有Java功能的设备。实际上,Java虚拟机在电子设备中司空见惯:电子书阅读器Kindle、蓝光磁盘 播放机和智能电话(包括不太智能的手机)等。iPhone(手机上网)应用程序可以在成千上万部iPhone上运行,但Java嵌入在26亿部手机上,从 不太智能、20美元就能买到的手机,到最新一代的黑莓和Android手机无一不包。请戈斯林到OpenWorld大会上演讲,只是Oracle掌门人拉里埃利森(Larry Ellison)希望向工程师们一再保证这门语言前途光明的手段之一。Oracle想要并购Sun,但它仍得等待欧洲监管部门批准这一决策。美国政府已开 了绿灯,但欧洲政府官员由于担心MySQL的发展还没有同意这一起交易。戈斯林和Sun董事长麦克尼利(McNealy)都表示,一旦并购工作完 成,Java会从Oracle得到比以往更多的关注和资源。从近期来看,埃利森传达的信号也许不是很重要,因为如今Java已成气候,要改变发展方向也并不容易。当然,也有一些人认为,Oracle的商业模 式太不一样了,所以它必然会对Java生态系统的每个部分进行重大变化。总体来说,每拿出一个Java可能变化的理由,就有同样充足的理由表明 Oracle可能还是希望保持现状。企业级应用是主战场Java最先在服务器端找到了自己的位置,未来这个领域仍是有望看到Java虚拟机的主要地方。对Oracle的所有产品来说,大型服务器也是主要 的安身之处,所以出现这对组合自在情理当中。虽然PHP编程员青睐MySQL,但对数据密集型的企业应用来说,许多祥郑最要紧的项目还是使用基于Oracle 的架构封装而成的Java,这种情况应该不会很快发生变化。Sun称,GlassFish应用服务器每个月的下载量超过100万人次,Tomcat等比较旧的平台仍然很常见。由于Java这项技术备受推崇、 运行速度快、真正跨平台,大型企业(如银行和保险公司)对Java开发人员求之若渴。不过,Java不再被认为是最新最酷的语法。一些编程员对静态类型语言的结构满腹牢骚,纷纷改用更新颖或更简单的语言,比如Ruby、Python 或PHP。现在许多较简单的Web应用程序就是用这些语言开发而成的,因为它们编写的代码容易修改,能快速建立原型。然而,这些使用便捷的新语言常常离不 开Java: Ruby开发人员常常使用JRuby(基于Java实现的Ruby语言),因为Java虚拟机能够更出色地处理繁重任务、释放多个线程。Jython(基 于Java实现的Python语言)也相似。Java现在正在加入一些最新的编程技术,以此遏制这些新语言大举入侵。Grails明显模仿了Ruby on Rails的许多简单的说明性模式;Grails这种框架利用名为Hibernate的数据库中间件,把Groovy等脚本插件结合起来。Groovy本 身添加了众多的动态选项便于代码解释,同时可以直接链接至Java应用编程接口(API)的任何部分。甚至不需要考虑Python或Ruby,因为 Groovy凭借一种精巧、现代的语法,让Java编程员可以使用似乎变化无穷的庞大库和底层稳若磐石的虚拟机。走上移动之路Java手机的数量(估计约26亿部)委实惊人,因为市面上凳判许多最简单的手机里面都运行Java平台微型版(Java ME)。这让Wattpad点抗 等公司得以构建在整个第三世界都能顺畅运行的文档阅读平台。不过,运行Java的智能电话数量相对少一点。iPhone的巨大成功激励许多人重新学习Objective C,这门语言让编程员对于内存使用等一些系统问题提高了控制能力。Java为编程员隐藏了大部分底层问题,这是个优点,但前提是不需要管理内存等资源,因 为要是垃圾收集出现一个小失误,有些游戏就运行不了。可遗憾的是,因为电池续航时间是极其重要的一个因素,智能电话需要比几乎其他任何平台更严格的资源管 理。不过,Java编程员仍然很吃香,因为黑莓手机在其新平台上继续采用Java ME:它为手机的情景模式(profile)添加了支持触摸屏和方向感应器的功能。而Android存在不可预知的因素。由于谷歌开放了Android的 使用,许多手机厂商搭上Android这辆彩车。谷歌的Android建立在开源Apache Harmony及其类上,而不是建立在Sun开发的Java开发工具包(JDK)和Java ME上。对使用Eclipse编写代码的人来说,它们看上去几乎一模一样。在其他许多情况下也无关紧要,因为Android开发使用了很多XML表单,但 如果这两套开发框架离对方渐行渐远,这种分裂可能会变成大问题。收复桌面阵地大多数人仍然认为Java在桌面端从来没有取得成功,这是过去。如今,Java正在缓慢而稳步地渗入到现代操作系统的各个角落。虽然用Swing编 写的标准应用程序因试图定位在每个平台的最基本部分而继续遭殃,但是有了像JavaFX和Web Start这些比较新的开发平台和框架,就有可能通过Web有效地部署软件。本地平台可处理Java归档(JAR)的所有缓存工作。只要点击链接,有时偶 尔随后点击几下授予权限的对话框,软件就可以安装及更新,还可以随时运行。JavaFX仍然是一个名副其实的未知因素。图形功能现在可与Adobe的Flash相竞争;计算引擎可支持大部分的Java API,但这门语言是一门奇怪的混合语言,融合了正宗Java、JavaScript及其他的一些标记语言。其代码比正规的Java简单,所以Java编 程员又要学习新的东西。不过,对极具互动性的桌面工具而言,新的动画类也许值得花时间学习。Web Start正在继续慢慢改进通过浏览器直接把软件部署到桌面的功能。抢占嵌入式领域Java还在人们最预料不到的地方茁壮成长。虽然C编程人员可能从来不会承认Java虚拟机巧妙处理存储区、快速运行的功能,但Java在非智能手 机、机顶盒、嵌入式芯片、Kindle及其他低功耗设备取得的成功表明:Java虚拟机完全有能力在嵌入式应用方面一展身手。Java的普及性还帮助编程 人员从大平台迁移到小平台。虽然为大型机开发企业级应用软件改成开发小型嵌入式代码并不简单,但Java标准大大简化了这种转变,这让其他许多工具自叹弗 如。Java程序包也在变得越来越小巧。戈斯林用尘埃来形容一台硬币大小、能够识别Java的计算机。JavaCard是面向这类小型程序包的一种虚拟 机和API,它即将迎来3.0版,这个里程碑式版本将增添网络连接功能。尽管这些小不点还没有小得足以放入到人的眼睛中,但直接与互联网通话的功能却让它 们显得极具诱惑力。合作伙伴会分道扬镳?所有开发人员的最大担心是:要是Oracle收购Sun的交易尘埃落定,会出现什么样的利益冲突变化?Oracle是靠收取大笔的软件许可费成长壮 大,其软件可运行在客户想要购买的任何硬件上。而另一方面,Sun通常是免费赠送软件,然后通过销售服务器赚到一些钱。这些经销策略也许不会立即发生变 化,因为惯性实在太太了,但谁也不知道将来Oracle会做出怎样的决策。一些人认为,Oracle过去在收取大笔许可费方面屡试不爽,只会鼓励埃利森对Sun采取类似的手法。也许Oracle的销售团队眼下就在垂涎这个 机会:针对Java以前免费的地方开始逐步提高许可费。为了避免重新编写Java平台企业版(Java EE)应用软件,许多企业很可能宁可支付每个CPU 100美元、200美元甚至100万美元的费用。批评人士指出,Oracle很容易开发出新版Java虚拟机,针对不同的市场推出不同的性能级别。桌面虚拟机可能保持免费,Oracle甚至可能会 掏钱请电脑厂商来推销Java和JavaFX,而处理极限多线程方面的性能改进可能会收取非常高的费用。从用户身上捞钱有好多法子,许可费相比之下往往便 宜得多:要是让拒不服从的编程员先学习一门新语言,然后重新编写代码库,那成本高多了。但也有人认为,Oracle也许不会采用这一招。一名接近Sleepycat(这家开源数据库公司在2006年被Oracle收购)的消息人士表 示,Oracle已把技术队伍的规模扩大了约一倍,而所有双许可模式原封不动。软件仍然采用开源或商业许可证这两种形式。如果Oracle像 Sleepycat那样对待Java,社区许可及其他方案仍然会跟以前一样免费、随处可得,同时有更多的工程师来改进代码。与其他各大Java合作伙伴的长期关系方面仍存在更深层的问题。谷歌继续支持Apache Harmony,这个代码超过125万行的项目似乎一心要破坏Sun作为世界中心的地位。IBM输掉了争夺Sun的竞标战,现在发现竞争对手Oracle 的实力更强劲了。IBM设计了Eclipse开发工具,可能也会开始把Java平台带往另一个方向。其他合作伙伴的态度比较激烈。SAP公司首席技术官Vishal Sikka一再要求Sun发布Java社区进程(JCP),着重提到了Oracle在2007年提出的方案:将控制权交由一家开放、独立、与厂商中立的标 准组织,标准组织的所有成员在机会均等的前提下参与。虽然Oracle对相关细节基本保持缄默,但可以认为,这家公司会因为从Sun承袭过来的一些观点而 重新赢得尊重。但是,尽管其他合作伙伴可能会参与恫吓的举动,但他们可能会考虑度的问题,因为大家其实是相互牵制的,任何过激的行为都极可能会被阻止,因为大家都 认识到一次编写、到处运行理念具有的优势。如果为Android手机编写的代码无法很容易地迁移至索尼蓝光播放机或Glassfish服务器,另一门语言 就有机会应运而生。实际上已经有多家公司在编写工具包,让用户可以在iPhone上轻松运行Ruby on Rails或Python软件。另外,许多这些比较新的语言可能会成为不可小觑的竞争对手,而暗斗过多只会帮助它们攻城掠地。现在有几十种非常好、知名度小一点的开源程序包,只要 忠实的爱好者稍加转换,通常就能把它们移植到每个平台上。比如,Python已经是一些科学领域的主要语言,谷歌选择Python、而不是Java作为其 应用引擎(App Engine)支持的第一种语言。虽然IBM、Oracle和谷歌在争夺主导权的竞争中可能会相互排挤,但它们必须认识到:所有人都受益于标准化,而不是 垄断。要是谁敢过于排挤别人、企图一手控制Java,其他厂商可能会奔向其竞争对手。Java也开应用程序商店?Java代码库仍相当有凝聚力、相对标准化,这个事实惹得众人猜测:Sun(如果合并案完成,还有Oracle)到底会怎样利用Java的普及性来 大发其财,又不提高许可费、挤压每个人?如果有人开发出一种面向整个Java生态系统的应用程序商店(App Store),从而像销售面向iPhone的应用程序那样销售用Java编写的小组件(widget)它们可以在桌面、手机、蓝光播放机或可以使用 Java的其他任何平台上运行,将会怎么样?最近已经有了面向Android手机的一批数量可观的应用程序,Sun也在谋划一家Java商店,好让人们只需把应用程序拖到桌面上,或者只要再编 一点代码,就可以把各应用程序结合起来,从而让它们可以在Java世界的几乎每个角落里运行。不过,处理截然不同的屏幕和用户界面还是个挑战。设想一下这种场景有多吸引人:开发人员编写的某个应用程序在Android手机上运行着,他在办公桌面上处理任务,回到家后在客厅的蓝光播放机上顺 畅运行。把Java应用程序带到坐沙发的人面前甚至有点出人意料,因为Java这门语言在被叫做Oak的早期阶段,本意就是运行在机顶盒上。这种远景将依赖 于Java平台的最大优点:普及性和跨平台的稳定性,也许这些优点会帮助Java给其发明者带来滚滚收入。