随笔-159  评论-114  文章-7  trackbacks-0
 
     摘要: 集合java.util.*一个对象,容纳多个对象,用于维护一系列相似对象。数组是一种简单集合。程序中,如何管理数据,需要一种数据结构。(数组是一种线形结构)。Java的集合框架是通过一系列接口和一些层级类形成的一套体系。通过接口来查看整个集合框架,并分类来进行学习和研究。 概述: Collection接口的一个对象会把数据按照一维线形组织。里面都是对象。List代表,会按照元素的相应顺序来组织...  阅读全文
posted @ 2005-12-06 23:13 北国狼人的BloG 阅读(900) | 评论 (1)编辑 收藏
     摘要: 内部类,使用内部类使编程更有层次,结构更清晰,但一切能用内部类解决的问题,外部类都能解决,只是编码是否繁琐的问题。内部类,是作为外部类的成员。内部类,修饰符可以为private protected static四种内部类成员内部类   局部内部类   静态内部类   匿名内部类1.成员内部类,可以作为外部类的...  阅读全文
posted @ 2005-12-03 19:59 北国狼人的BloG 阅读(417) | 评论 (0)编辑 收藏
面向对象高级

static,可以修饰属性、方法、代码块。

每个对象称为类的实例,对象之间的存储区互不干涉。

static int data;是类变量(共享),为类开辟一个空间。共享存储区域。

访问类变量,通过类名访问。一个对象引用也可以使用静态成员,与它的编译时类型的类访问,一致。

MyClass m = new MyClass();
m.data 《= 》MyClass.data;

静态方法-〉没有当前对象概念-〉也就不允许访问的类中的非静态成员(实例变量)

主方法之所以是静态的,它是程序入口,JVM最初没有对象,必须通过使用类名调用方法,主方法必须为静态的。

静态方法不能被覆盖。

静态代码块只执行一次。

static 用于单例模式Singleton模式

class DBConnection{
   
private static DBConnection db = null;
   
private DBConnection{}

   
public static DBConnection getInstance(){
         
if(db == null) db = new DBConnection();
         
return db;
   }

}


final 修饰  类、属性、方法

修饰类,无子类,保证用户使用的一致性。典型范例String类。

修饰属性或者变量一旦赋值,不得更改。

对于对象变量来说,是不能再指向其他对象,而现有的对象内部属性可以改变。

会配合static一起使用,只分配一个存储空间,只需要维护一个空间。

public static final,是一个常量。大写。

class SuperClass{
      final int AGE;

      public SuperClass(){
         AGE=10;
      }
}

初始值0不算,需要显示赋一次值。

初始设定在两个地方,1定义时直接赋值,2构造器

静态常量也在两个地方设定,1初始设定,2静态代码块




final方法不能覆盖,由于多态,一个编译时类型对应多个运行时类型,final保证某方法的稳定性。


private
               左边的修饰符有其中一个,系统都默认添加了final修饰符。
static


所以之前的静态方法不能覆盖。

=====================
方法继承是决定于在子类中是否可见。能见到就是继承。

final不决定继承。

实际上如果实例化一个子类对象,它的父类对象的所有属性(包括private成员都创建了,就是访问不了,所以不能成为继承的一部分,也就是不能继承咯)



=====================


abstract 修饰 类 方法

修饰类 -> 这个类必须被继承使用->不能生成对象

用处,把子类最大的共性提取出来放入其中,面向对象一般原则。

虽然不能生成对象(不能作为运行时类型),但可以声明为类型(可作为编译时类型)。

抽象方法,没有实现,留给子类覆盖。

final永远不可能和abstract在一起,那么private和static也不能和abstract联合修饰。

final表示必须不能被继承,不能覆盖;abstract表示必须继承,方法没有实现,必须覆盖使用。所以矛盾。

abstract class SuperClass{
      abstract void print(); //print(){},这是空实现,也是实现,所以不能带大括号。
}

如果类中有抽象方法的话,那么类只能是抽象类。(一个半成品)

如果子类没有实现父类的抽象方法,就会编译出错,因为子类继承了抽象方法,需要声明为抽象类。

SuperClass sc = new SubClass();

sc.print();动态类型判定,运行时类型不会改变,肯定是一个实现抽象方法的类对象。




接口:是同类,同一个层次的数据结构。

interface IA{
   void print();  
   int A = 1;
}

修饰符省略
一个Java文件,只能定义一个公开接口

一个接口等同于一个抽象类

一个特殊的抽象类:
   所有方法都是公开抽象的:public abstract
   所有属性都是公开静态常量:public static final

interface IA{
   void print();  
   int A = 1;
}

等价于

abstract class IA{
   public static final int A=1;
   public abstract void print();
}

这时可要注意,类实现接口时,覆盖方法的访问控制符一定要写上public,接口是省略为public,类不写可是default,根据Overriding规则,覆盖方法的访问控制等于或者大于父类方法的访问控制。

class IAImpl extends java.util.ArrayList implements IA{}

1一个类除了继承类,还可以实现接口(多个)。

2尽管一个类只能继承一个类,一个类可以实现多个接口

3接口与接口之间可以继承并可以多继承,实现多重继承,但复杂度不增加。

interface IC extends IA,IB{}

IC有着IA,IB所有方法的定义

IA,IB可以作为编译时类型。

========================

接口,被用来定义可以***的东西。

                  存储设备                              输入设备
----|----------------|-----                     ----------|-----------
硬盘                  U盘                                 鼠标
----|----
移动硬盘

使用接口来剥离出一部分抽象。

移动硬盘、U盘、鼠标除了间接父类是统一的设备父类外。

他们都是USB设备,这部分抽象就需要用接口定义。

那么机器上的连接器是一个方法,connect(USB接口),不管你什么具体设备,你都必须实现USB规范,才能往上插。

那么用接口来定义一个规范。


例子2,JDBC,使用Java来访问数据库。

首先,如果由Sun公司自己提供各种数据库的驱动,那么各个DB厂商需要把数据库核心代码提供给Sun,这是不可能的,核心商业机密。

而由各个DB厂商自己写的话,会出现方法名的不同,导致如果数据库迁移,代码需要改动。(例如Oracle提供的方法为ConnectOracle()而ms提供的方法为ConnectSQL)。那么无法真正实现Write Once,Run Anywhere,Sun不同意。

怎么办?使用接口。

由Sun和DB联合制定一些一系列接口。

interface Driver()
{
      void connect();
      ...
}

OracleDriver implements Driver
SQLDriver implements Driver

实现不同的connect()逻辑。

用户Driver d = getDriver();
d.connect();

接口是实现Java一次编译,到处运行的重要技术。

保证了Sun制定规范,数据库厂商实现,用户使用。保证架构稳定性(将三方分开)

对于用户来说,接口最大化屏蔽差异。

1.实现不同层次,不同体系的对象的抽象。
2.保证架构稳定性。对用户透明。


==============================

Object 类,所有类的父类(直接,间接父类)

finalize(),当一个对象被垃圾回收的时候,会调用一下。不适合放入释放资源的方法。

toString(),对象的字符串表现形式。

System.out.println(obj);->obj.toString()

自定义类,覆盖该方法,返回一些有意义的信息。

==  判断字面值是否相等,

String a = new String("hello");
String b = new String("hello");
b==a false

String final类,并且它的值也是immutable的。

String a = "A"
a = a + "B"
这两步操作一共产生了3个对象。

JVM内部有一个字符串池,一个独立存储区域,保存已创建的字符串,如果再有相同的,会将引用指向字符串池中的已有对象,不再创建新的,如果没有再创建。

String a = "abc";
String b = "abc";

所以上面的例子是采用new String("abc")方式创建String对象,不会再去池中找,直接在堆中创建新对象。

String a = new String("hello");
String b = "hello";

a为堆地址,b为串池地址,a==b,false。

这种方式,是一种用时间换空间的做法,比如如果程序中有100个"hello",难道程序要去维护100个对象嘛。

Object.equals   判断对象值是否相等。

/*
 * Student.java
 *
 * Created on 2005年12月3日, 上午10:43
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 
*/


package javaapplication1;

/**
 *
 * 
@author Administrator
 
*/

public class Student {
    
    String name;
    
int age;
    
    
/** Creates a new instance of Student */
    
public Student() {
    }

    
    
public Student(String n,int a){
        
this.name = n;
        
this.age = a;
    }

    
    
public boolean equals(Object o)
    
{
        Student s 
= (Student)o;
        
if(s.name.equals(this.name)&&s.age == this.age)
            
return true;
        
return false;
    }

    
}

自定义类如果要进行对象值的比较,覆盖Object的equals方法,自行判断,如果不覆盖,直接调用Object.equals是判断地址。

equals方法覆盖标准流程:

    public boolean equals(Object o)
    
{
        
if(this == o)
            
return true;
        
if(o == null)
            
return false;
        
if(!(o instanceof Student))
            
return false;
        Student s 
= (Student)o;
        
if(s.name.equals(this.name)&&s.age == this.age)
            
return true;
        
return false;
    }

double d = 10000.0d;
Double D_d 
= new Double(d);
String D_S 
= D_d.toString();//D + ""
String d_s = String.valueOf(d);//d + ""
double s_d = Double.parseDouble(d_s);
Double S_D 
= Double.valueOf(d_s);
double d_D = D_d.doubleValue();












 

posted @ 2005-12-02 00:03 北国狼人的BloG 阅读(381) | 评论 (0)编辑 收藏

面向对象三大基石:封装,继承,多态。面试会问到。

Overriding  覆盖  只存在于父子类之间,一定。

什么时候才是覆盖呢?

class Father{
   public void run(){
   }
}

class Son extends Father{
   public void run(int a){
   }
}

注意:这是方法的重载,不是覆盖!只是这个重载发生在父子类之间。

覆盖是,子类参数列表与返回值都与父类相同,并且子类在覆盖父类方法时,不能给出更严格的访问控制,并且子类方法例外的类型是等于父子方法抛出的异常类型,或者是其子类型。

The exceptions thrown by an overriding method must be equal to or a subset of the exceptions thrown by the overridden method.

注意构造方法根本不能继承,所以不存在覆盖的问题。

访问控制

private 本类内部可见

default 同类同包

protected 同包+不同包子类

要构造一个对象,先构造父类对象,再构造子类对象

构造一个对象的执行过程。

1.递归的构造父类对象-----------〉也就是说父类本身也要走这样的步骤。
2.顺序调用成员属性赋初值语句
3.调用本类构造方法

后来课程领悟,类加载与构造对象是两回事,类加载过程,1.static静态成员加载,2运行static一次,静态代码块,3如果有静态内部类,赋值,对静态内部类的赋值是指编译产生的Employee$SomeInner.class文件的读取。

如果类有静态变量或者静态块,而且用到时(static初始化只有在必要的时候才会进行,那么就会在第一步之前执行一遍,先静态变量,然后静态块,以后再怎么new都不会执行,回到创建父类开始。

======〉引用Think In Java

在这里有必要总结一下对象的创建过程。请考虑一个名为Dog的类:
(1) 类型为Dog的一个对象首次创建时,或者Dog类的static方法/static字段首次访问时,Java解释器必须找到Dog.class(在事先设好的类路径里搜索)。
(2) 找到Dog.class后(它会创建一个Class对象,这将在后面学到),它的所有static初始化模块都会运行。因此,static初始化仅发生一次——在Class对象首次载入的时候。
(3) 创建一个new Dog()时,Dog对象的构建进程首先会在内存堆(Heap)里为一个Dog对象分配足够多的存储空间。
(4) 这种存储空间会清为零,将Dog中的所有基本类型设为它们的默认值(零用于数字,以及boolean和char的等价设定)。
(5) 进行字段定义时发生的所有初始化都会执行。
(6) 执行构建器。正如第6章将要讲到的那样,这实际可能要求进行相当多的操作,特别是在涉及继承的时候。

=====================

多态-1.编译时多态      方法重载
         2.运行时多态      一个对象可能会具有多个类型

对象是客观的。

人类对对象的认识是主观的

当人看到一个不能识别的,有生命的,区别人的东西时,会类来认识该事物。

也就是Animal a = new Dog();子类对象可以使用父类对象来引用。

Animal被称为编译时类型,而a真正的对象类型是运行时类型。

3个原则:

1.对象不变(运行时类型不变)(客观的肯定不会改变)
2.只能调用编译时类型的方法,方法调用时,检查编译时类型内部是否定义了该方法。
   也就是说,在你以一个一个动物来看待一只狗时,你是不会知道它有散步的方法的。
3.RTTI,运行时,动态类型判定(看运行时类型),子类覆盖了(Overriding)父类方法,那么调用运行时类型对象的方法。

a instanceof 类名(编译时类型)
a为对象变量
判断a是否被声明为后面类的对象。
用在强制类型转换之前。如果转换错了,java.lang.ClassCastException 运行时例外

记住,方法只有覆盖时,调用寻找运行时类型。而Overloading ->编译时多态->看编译时类型。

属性,重载阿,都要看编译时类型。

package com.ljl;

public class TestClass {
    
public void print(B b){
        System.out.println(
"is B");        
    }

    
//    public void print(A a){
//        System.out.println("is A");
//    }
    
    
public static void main(String[] args)
    
{
        TestClass tc 
= new TestClass();
        A a 
= new B();
        tc.print(a);
    }

}


class A{}

class B extends A{}

为什么子类覆盖父类方法时,访问控制符只能更宽泛。因为如果父类方法为public,子类方法为private,那么多态时,察看父类方法可以调用(可调用编译时类型所定义的方法),而动态类型判断时,调用子类方法,发现为private,完蛋了。



posted @ 2005-11-29 21:37 北国狼人的BloG 阅读(387) | 评论 (0)编辑 收藏

面向过程是以时间为顺序的,组成单位是函数。

面向对象是一套思想。它来源于人类对于客观世界的认识的一般规律。

1什么是对象?

什么都是对象!客观存在的就是对象。

对一个事物来说,一是它有什么?(属性)二是它能做什么?(方法)



2为什么面向对象

它人类看待客观事物的一般规律。

人看到事物,首先会想到它能做什么,功能,存在的价值。并不太关心它的属性。

========================================

要注意联系实际来搞懂面向对象,比如面试这件事,实际上,公司是想测试你是否能提供 公司需要的方法,公司并不关心你实现的细节。录用后,就是开始去调用你的方法。如果不能很好的实现方法,就可能被辞退。

那么那些笔试、测试就是想看你是否有知识,知识就是属性,记住属性与方法之间是有联系的,也就是没有公司所需的知识,可以断定这个人肯定不会有公司需要的方法。

一个事物的方法的实现细节是对外界屏蔽的。

那么,之前提交的简历是什么呢,那就是一个方法列表阿,API。比如年龄22,表明你的方法可以很好的被调用;未婚,告诉别人,你可以加班,放心用。

项目1,2,3,每个项目后面一定要写上你在项目中用到什么语言,否则HR的人是不知道你想告诉他们什么,他们只关心公司想要一个有JSP开发经验,或者什么什么技术有经验的人。您叙述一大堆项目的事情,没有任何意义。所以简历不要瞎写。

面试是什么,就是想真正调用一下你的方法,测试一下。

=======================================

那么社会的运转就是各个对象的方法的相互调用。

方法列表公开,方法的实现细节屏蔽。

属性,可见和不可见

一个方法的实现细节谁知道呢?只有这个对象的生成者。



那么人看待客观世界的认识,就是通过类。人类认识的是类。

类是一系列对象的抽象,对象的模版。

一类事物,属性、方法。这类对象也肯定有这些属性和方法。



为什么面向对象的第二点,就是使得开发的系统各思其职,各尽所能。也就是低耦合,高内聚。

为什么,电脑中的部件可以很容易的更换成为其他厂商的,就是因为主板与具体部件的连接是松散的;那为什么,可以很容易的换到其他厂商的呢,是因为各个厂商遵循着标准接口。

比如硬盘的use(电源接口,数据接口),每个厂商都必须实现,而且硬盘是一个类的概念,有属性,比如尺寸。

各个厂商不能在别处下功夫,只能对硬盘内部进行调整,提高性能,才会免予被替换。

高内聚是指完成功能的最小化。

低耦合表现在提高了对象的复用性,比如中间件。



最后总结一下,面向过程是先有算法,后有数据结构。由若干个过程相互调用完成。

面向对象,则是先有数据结构,后有算法,以对象为中心,开发一系列类,拿到特定对象,通过对象之间通信,对象设计要简单。

类(共性)--〉对象(类允许对象在满足共性的同时,存在个性)

一个类,则是一个新的数据类型。



实例变量与局部变量命名冲突,则使用局部变量,除非使用this.来指定某个属性。

调用构造器只是生成对象步骤的最后一步,不是构造对象本身。

方法中使用了this,this表示当前对象,当前对象就是谁调用该方法,谁就是当前对象。

class TestClass{
String name;
public void printAll(String name)
{
   this.name = name;
}

}

上面必须添加上this.来引用实例变量name。因为在局部变量和实例变量冲突时,使用局部变量。





finalize()不是析构方法,因为不能存在真正的释放空间操作。



方法参数,简单类型传值,对象类型传引用(一个实际存储[堆中]的首地址)。

假如方法中,引用赋予一个新的对象,那么方法执行完以后,该引用和实际地址消失。传入引用所指向的对象属性不变。



Overloading,修饰符和返回值可以不同,但参数列表(参数类型个数或者排列顺序)一定要不同。

Overloading,是编译时多态。那么它要看编译时类型。

Overloading,也存在于父与子的关系当中。父有方法,子类可以有同名方法,只有参数列表不同才是重载。

构造器(构造方法可以重载),通过this();可以调用本类无参构造方法。
在其他构造器调用其它构造器,那么需要this关键字,并且必须放置于第一行。

如果一个类不写任何构造函数,系统会默认添加无参空构造方法。不要依赖系统默认行为!自己最好写上。javap查看实际代码。


对于简单类型,如果调用方法传入参数的类型不存在,那么就采用向上匹配原则进行查找。

m(byte)不存在,就用m(short)。(实际上long是int的父类,int是short的父类)



封装

属性尽可能私有。

方法尽可能公开。

private只有类内部本身能访问。

default只有同包能访问。

protected只有存在继承关系,才能访问。

posted @ 2005-11-28 23:43 北国狼人的BloG 阅读(500) | 评论 (2)编辑 收藏

模式是什么?

模式是一个范式,一个在相同环境或者状况下的一种通用解决办法,解决方案。就好像孙子兵法,对于某种特定战局,战况下的一种派兵布阵策略和实施步骤的总结。

模式需要什么呢?

模式需要一个名字,一个问题域(要解决的问题),要有一个解决的方案,最后要达到什么样的结果。

长话短说,Observer模式,所要解决的问题就是,一个事物,当它自身的状态改变了,那么它要通知其他的事物,而它又不能够事先知道要通知谁,只有在Runtime时才能知道。

举个例子吧,钟表和人的关系就是这样,钟表自身的状态,也就是时刻改变了,它通知某些人,某些人看到或者听到后,会做出不同的行为。而钟表在商店里时,并不知道要通知谁?只有买主把钟表买回家,买主的家人注册到这个钟表,这时,钟表的状态改变才会通知到家里的人,那么家人有大人、小孩,他们看到或者听到这个钟表的时间改变,会有不同的行为。

那么将上面的例子可以化解为对象。钟表是个源,它是抽象的概念,可以很多形式的表,手表、挂钟、闹钟等,而家人们都是监听器,实现了监听器接口,监听器方法就是listen()和see(),当人每个人实现了接口会有不同的行为,这些钟表并不关心,它只会在整点时通知之前注册到它内部的家人实例的监听器方法。

那是什么时候注册的呢?就是主人买回家,告诉家人这是新的钟表,也就是Timer.registerListener(Listener l)

那么钟表就是observable,就是那个常说的Subject,而家人就是具体的Observer,实现了Oberver接口的方法。

package com.javapatterns.observer;

public abstract class AbstractTimer {
    
    
public void attach(){};
    
    
public void detach(){};
    
    
void notifyObservers(){};
}

 

package com.javapatterns.observer;

import java.util.Enumeration;
import java.util.Vector;

public class ConcreteTimer extends AbstractTimer {

    
private Vector observersVector = new java.util.Vector();
    
    
public void attach(Listener observer)
    
{
        observersVector.addElement(observer);
    }

    
    
public void detach(Listener observer)
    
{
        observersVector.removeElement(observer);
    }


    
public void notifyObservers()
    
{
        Enumeration enumeration 
= observers();
        
while (enumeration.hasMoreElements())
        
{
            Listener l 
= (Listener)enumeration.nextElement();
            l.see();
            l.hear();
        }

    }



    
public Enumeration observers()
    
{
        
return ((Vector) observersVector.clone()).elements();
    }

    
}

下面是Listner接口,是一个概念模型,提供给Timer,Timer只关心,自身改变状态后,要调用的观察者什么行为,并不关心观察者本身。所以提取人的若干行为,抽象成为接口。

package com.javapatterns.observer;

public interface Listener {
    
    
void see();
    
    
void hear();

}

 

package com.javapatterns.observer;

public class Host implements Listener {
    
    
private String name;
    
    
private short age;
    
    
private String sex;
    
    
public Host(String name,short age,String sex){
        
this.name = name;
        
this.age = age;
        
this.sex = sex;        
    }


    
public void see() {
        
// TODO add see default behavior

    }


    
public void hear() {
        
// TODO add hear default behavior

    }

    
    
public void otherBehavior(){
        
    }


    
public short getAge() {
        
return age;
    }


    
public void setAge(short age) {
        
this.age = age;
    }


    
public String getName() {
        
return name;
    }


    
public String getSex() {
        
return sex;
    }


}


这是一个主人的类,也就是一类具体的Observer。

output.jpg


接口java.util.Observer和类java.util.Observable是Java本身对于观察者模式的支持。

其实这种模式就是一种回调的应用,就是想其它类中注册自己的接口,到特定时候调用自己的方法。

就好像古诗词中,“有朋自远方来不亦乐乎”,意思是说,如果好友光临到门口,叫一声自己,就会很高兴,也就是说,告诉朋友到达自己住处,这个状态满足,那么就叫一声自己,自己就会为朋友开门,高兴等行为就会进行。 如果不采用观察者模式,那就是自己需要不断的到门口察看朋友是否到了,是一种轮循的方式,当然也能达到效果,但会影响自己的事情。

posted @ 2005-11-27 11:26 北国狼人的BloG 阅读(434) | 评论 (0)编辑 收藏
第一次使用Linux,在这上做Java开发.

在Fedora Core 3的发行版中,附带的是GNU版的JRE,下载的最新的 Eclipse SDK 3.1.1,解压以后,根本不能正常启动界面。

由于我们一般能够获取的Linux发行版本都是免费的版本,而不是Professional或者Enterprise Server级别的,这些版本对Sun的JDK支持都很有限


版本检查

我们这个时候可以打开一个命令行终端,输入"java -version",可以看到如下信息:

[ljl@localhost ~]$ java -version
java version "1.4.2"
gij (GNU libgcj) version 4.0.0 20050519 (Red Hat 4.0.0-8)

Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

看到了吧?这并非Sun官方的Java。

我们需要到Sun的网站上下载最新的JDK,目前的版本是JDK 5.0 Update 5,注意,这里有两个版本:jdk-1_5_0_05-linux-i586-rpm.bin和jdk-1_5_0_05-linux- i586.bin,根据Fedora Core 3的Release Notes说明,应该使用后者,也就是不带rpm的版本。(我用的是jdk-1_5_0_05-nb-4_1-linux-ml.bin,连NetBeans4.1都带了,哈哈)

同时,我们也需要到eclipse.org上下载最新的Eclipse SDK,目前版本3.1.1。需要根据你的系统环境选择合适的下载包,如:我的电脑是x86的,X Window系统用的是GNOME 2.10.0,那么自然应该选「x86/GTK 2」,文件名eclipse-SDK-3.1.1-linux-gtk.tar.gz。需要说明一下,FC3默认的X Window系统是GNOME,但是在KDE环境下,照样可以正常使用GTK的应用程序。


安装和配置

我们现在打开一个命令行终端,输入命令su,提供root用户密码,进入管理员操作模式。然后用ls -l看一下刚刚下载的jdk-1_5_0_05-linux-i586.bin,可以看到它的权限是-rw-r--r--,所有者为sean。为了能够执 行它,需要更改它的权限设置。敲入命令chmod +x jdk-1_5_0_05-linux-i586.bin,再看权限,-rwxr-xr-x,可以执行了。

切换到/opt/目录,运行jdk-1_5_0_05-linux-i586.bin即可。注意:在Linux默认PATH不包含当前目录,即".",因 此执行当前目录的文件,正确的方法是在文件名前面加上"./"。成功以后可以发现在/opt/目录下多了一个jdk1.5.0_05子目录,这就是我们的 JAVA_HOME。

到这里还没完,在终端里检查java -version找到的仍然是原来的GNU版本,我们还需要配置系统的环境变量PATH。检查目前PATH内容的方式是echo $PATH,为了能够直接找到我们自己的java,需要把/opt/jdk1.5.0_05/bin目录加入PATH,并且要在GNU版本的前面,最保险 的办法当然是放到最前面了。方法是PATH="/opt/jdk1.5.0_05/bin:$PATH"。这之后再敲java -version,出来的就是正确的了:

[sean@localhost Java]$ java -version
java version "1.5.0_05"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode, sharing)

为了今后登录的时候就把这个路径加到环境中,需要修改一下.bash_profile,先cd ~进入自己的主目录,然后用emacs或者vi编辑这个文件,找到PATH这一行,改成:
PATH=/opt/jdk1.5.0_05/bin:$PATH:$HOME/bin
保存,退出,注销然后重新登录。

接下来要做的就是把Eclipse解压到一个你认为合适的路径。


开始使用

有很多方式运行我们的Eclipse:命令行或文件浏览器直接打开都可以。我这里告诉大家一个在GNOME里面比较方便的一种途径:从文件浏览器把eclipse运行文件拖放到系统的面板上,给它一个名字和图标,今后就可以直接点这个面板图标启动Eclipse了。

亲切的Eclipse又出现了,Great!Let's JAVA!
posted @ 2005-11-26 19:23 北国狼人的BloG 阅读(488) | 评论 (0)编辑 收藏
从我第一次认识达内,就是公开课,当然也是免费的.但质量很高,都是资深专家进行讲座.这是达内认真做事的一种侧面表现.

在这里,有经验的精英会和你分享经验,这是无私的,他们原意告诉你IT业界的动态,帮您分析您所处位置,进入IT行业,或者提升职位,要做哪些努力.无论您是否参加达内培训,都可以进行深入交流.

有一点,大家也要注意,达内各个级别的员工都是每周六不休息的,咨询专家,技术专家,人力资源资深专家,每周都有会提供给大家讲座,提供交流的机会.这是 一种反应公司理念的态度.如果再次选择,我仍然选择达内,因为至少我在达内的每时每刻,我永远不会感受到无助.我反倒是觉得现在怎么问题少了,没问题请教 达内的精英,呵呵.

就到这了,假如您在IT职场遇到困惑,可以考虑去听一听,会有收获的.






posted @ 2005-11-26 16:51 北国狼人的BloG 阅读(827) | 评论 (1)编辑 收藏

作为程序员,思维要缜密,对于技术人员,创造只是一小部分,大部分还是要脚踏实地。

所以每个问题一定要想到各种情况,测试人员可能会用你想不到的数据进行测试。

练习1:计算某数的阶乘!

package com.ljl;

public class Factorial {
    
    
public static void main(String[] args)
    
{
        
try{
            
int num = Integer.parseInt(args[0]);
            
if(num < 0)
            
{
                System.out.println(
"please input positive number!");
                System.exit(
0);
            }

            
if(num > 170)
            
{
                System.out.println(
"this program can't calculate this num!");
                System.exit(
0);
            }

            
double result = 1d;
            
for(int i = 2; i <= num; i++)
            
{
                result 
*= i;
            }

            System.out.println(
"The factorial of " + num + " is " + result);
        }

        
catch(Exception ex)
        
{
            
if(ex instanceof ArrayIndexOutOfBoundsException)
            
{
                System.out.println(
"Please input the num to calculate!");
                System.exit(
0);
            }

            
if(ex instanceof NumberFormatException)
            
{
                System.out.println(
"Please input a number!");
                System.exit(
0);
            }

            System.out.println(
"error occured!please run it again!");
            System.exit(
0);
            
        }
        
    }

}


那么对于数据输入的合法性判断,对于数据是否合理,对于程序是否能够计算所有的数,有无上界。

记住,即使不能计算,也要告诉用户,决不能给用户提供错误的答案!!

result 类型如果为int只能算到12,如果为long能算到20,如果为float只能算到32,如果为double,则可以算到170。

为什么double和long同占用8个字节,为什么表示数的范围差那么多?因为double类型支持科学计算法。

The factorial of 170 is 7.257415615307994E306

所以可能用指数方式来表达大数。

那么如果表示170以后的数的阶乘呢?可以猜用类,也可以找两个变量,一个存底数,一个存指数。


=================================

数组

int[] mark = new int[10];40字节存储空间。

-----------------------
对于局部变量,需要初始个值。

而局部变量的数组,不需要初值,会根据类型给定相应默认值。数值为0/0.0,布尔false,对象null,char /u0000

----------------------

mark 是一个int[]数组类型的对象,它保存的是那40字节存储空间的首地址。

Java中,引用和地址都保存在栈中,而具体的值开辟的空间存储在堆中。


System.arraycopy(a,0,b,0,a.length);
int[] a = {1,2,3,4,5}
int[] b = new int[10];
a.length

数组特点
1.不可变长
2.可以保存简单类型数据
3.查找快,插入和删除效率低。



2维数组

int[][] a = {{1,2},{3,4},{5,6}};
int[][] a = new int[3][];
a[0] = new int[2];
a[1] = new int[3];
a[2] = new int[1];

a类型?是一个对象,但是是虚拟机级别对象,无法用getClass().getName()显示。

哥德巴赫猜想

package com.ljl;

public class Goldbach {
    
    
public static void main(String[] args)
    
{
        
int num = Integer.parseInt(args[0]);
        
if(num < 6)
        
{
            System.out.println(
"the num must larger than six!");
            System.exit(
0);
        }

        
if(num%2 != 0)
        
{
            System.out.println(
"it should be a even!");
            System.exit(
0);
        }

        
for(int i = 1; i <= num/2; i++)
        
{
            
if(isZhiShu(i)&&isZhiShu(num-i)){
                System.out.println(num 
+ "=" + i + "+" + (num-i));
                
break;
            }

        }

        
    }

    
    
private static boolean isZhiShu(int num)
    
{
        
for(int i = 2; i <= (int)Math.sqrt(num); i++)
        
{
            
if(num%== 0)
                
return false;
        }

        
return true;
    }

}

posted @ 2005-11-25 23:35 北国狼人的BloG 阅读(296) | 评论 (0)编辑 收藏
变量

1.对局部变量,要先赋值,后使用。
2.一个局部变量,作用域,是定义它的代码块

public class Test{
   public static void main(String[] args){
        {
            int a = 4;
         }
         System.out.println(a);          
   }   
}

a的作用域在main里面的两个括号之间。所以,此程序编译不通过。cannot resolve symbol

3.对于两个局部变量,在同一作用域内不允许两个同名变量出现。

public class Test{
   public static void main(String[] args){
      int a = 6;
      {
         int a = 4;
      }
      System.out.println(a);
   }

}

在小代码块,重了。Duplicate local variable a。

------------------------------

命名规范

1.语义
2.包,所有字母小写
3.类,所有单词首字母大写
4.变量、方法,首字母小写,其余单词首字母大写
5.常量,所有字母大写


byte b=1;
b=b+1;报错,因为b+1运算后,系统转为int,无法隐式转换
b+=1;不报错。请查看JVM,字节码差异。



>>   右移  除2,左补符号位
<<   左移  乘2,右补0
>>>  右移,左永远补0

虽然比乘除运算符快,但是有问题。

12>>32

回变为12。

12&9    按位与
12|9    或
12^9   异或

(a>b)&(c>d)
非短路方式,都判断,并不会因为a>b为假而不进行后面表达式的判断。

(a>b)&&(c>d)
短路方式,a>b为假,后面不执行,直接返回false。

int i = 3;
int count = (i++)+(i++)+(i++);
count = 3 + 4 + 5
            i=4  i=5  i=6

int i =3;
i = i++;
那么流程如下

i++这个表达式的值是3。然后执行i自加1,变为4(因为++操作比赋值优先级高),最后i 再次被赋值为3。



不记运算符优先级,最好用括号老解决,很明白,否则像这样的b+++a表达式,实际上(b++)+a。
posted @ 2005-11-24 23:26 北国狼人的BloG 阅读(375) | 评论 (0)编辑 收藏
仅列出标题
共17页: First 上一页 9 10 11 12 13 14 15 16 17 下一页