程序设计基本概念

一、C程序设计

• 结构化程序:用三种基本结构(顺序结构、选择结构、循环结构)组成的程序










void	 clearerr(FILE *);
int	 fclose(FILE *);
int	 feof(FILE *);
int	 ferror(FILE *);
int	 fflush(FILE *);
int	 fgetc(FILE *);
int	 fgetpos(FILE *, fpos_t *);
char	*fgets(char *, int, FILE *);
FILE	*fopen(const char *, const char *);
int	 fprintf(FILE *, const char *, ...);
int	 fputc(int, FILE *);
int	 fputs(const char *, FILE *);
size_t	 fread(void *buf, size_t size, size_t count, FILE *fp);
FILE	*freopen(const char *, const char *, FILE *);
int	 fscanf(FILE *, const char *, ...);
int	 fseek(FILE *, long, int);
int	 fseeko(FILE *, off_t, int);
int	 fsetpos(FILE *, const fpos_t *);
long	 ftell(FILE *);
off_t	 ftello(FILE *);
size_t	 fwrite(const void *buf, size_t size, size_t count, FILE *fp);
int	 getc(FILE *);
int	 getchar(void);
char	*gets(char *);


const  int MaxLine =1000; // 值不可修改

int  r=6;
int * const pr=&r;       // 指针pr不可修改,但*pr可修改

const  int  *p;          // 指针p可修改,但不可以通过指针对变量重新赋值,即不能对*p赋值

int x;
const  int  *const  px=&x // px和*px都不可修改

二、C++程序设计




三、Java程序设计



• Java保留关键字



• Java数据类型


• 数组

   1) 一维数组:

       基本数据类型   数组名[ ] ; // 声明一维数组
       数组名 = new 基本数据类型[个数] ; // 分配内存给数组


       基本数据类型   数组名[] = {初值0,初值1,…,初值n}

       数组元素个数:数组名.length

       System.arrayCopy(source,0,dest,0,x):语句的意思就是:复制源数组从下标0开始的x个元素到目标数组,从目标数组的下标0所对应的位置开始保存

       Arrays.sort(数组名)为数组排序的操作,但这个方法在java.util这个包里面

    2) 二维数组
        基本数据类型 数组名[ ][ ] ;
        数组名 = new 基本数据类型[行的个数][列的个数] ;


        基本数据类型  数组名[ ][ ] = { {第0行初值},
                                                       {第1行初值},
                                                        …
                                                       {第n行初值},
                                                     };


         每行的元素个数不同的二维数组:

           int num[ ][ ] = {

                                   {42,54,34,67},
                                   {33,34,56},
                                   {12,34,56,78,90}
                                 };        

           行数:数组名.length // 取得数组的行数
           列数:数组名[行的索引].length // 取得特定行元素的个数   

           二维数组作为参数或返回值: 

                 1) 形参:基本数据类型  数组名[ ][ ]      

                 2) 实参:数组名

    3) 对象数组

        Person p[ ] ; // 声明Person类类型的数组变量
        p = new Person[3] ; // 用new分配内存空间
        p[0] = new Person () ; //用new产生新的对象,并分配内存空间给它
        p[1] = new Person () ; //用new产生新的对象,并分配内存空间给它
        p[2] = new Person () ; //用new产生新的对象,并分配内存空间给它
        或
        Person p[] = {new Person(),new Person(),new Person()} ;


• Java 类(class)

     


    创建对象:类名 对象名 = new 类名() ;

    访问属性:对象名称.属性名
    访问方法:对象名称.方法名()

    封装属性:private 属性类型 属性名
    封装方法:private 方法返回类型 方法名称(参数)

    “匿名对象”,顾名思义,就是没有明确的声明的对象。读者也可以简单的理解为只使用一次的对象,即没有任何一个具体的对象名称引用它。(如:new 类名.方法())


• 对象的比较

  有两种方式可用于对象间的比较,它们是“= =”运算符与equals()方法,“= =”操作符用于比较两个对象的内存地址值是否相等,equals()方法用于比较两个对象的内容是否一致。

  “==”是比较内存地址值的,“equals”是比较内容的。

String str1 = "java" ;
String str2 = new String("java") ;
String str3 = "java" ;



• 用this调用构造方法

class Person
{
	String name ;
	int age ;
	public Person()
	{
		System.out.println("1. public Person()");
	}
	
	public Person(String name,int age)
	{
		// 调用本类中无参构造方法
		this() ;  //必须放在首行
		this.name = name ;
		this.age = age ;
		System.out.println("2. public Person(String name,int age)");
	}
}


• static关键字的使用

  1) 静态变量(类变量):

     所有的对象都指向同一个static属性,只要当中有一个对象修改了static属性的内容,则所有对象都会被同时修改。
用static方式声明的属性,也可以用类名直接访问,即:类名.static属性 ;

  2) 静态方法(类方法) 
      static可以用其来声明方法,用它声明的方法有时也被称为“类方法”,访问方法:类名.static方法;

  3) 静态变量与静态方法的关系

      如果在类中声明了一static类型的属性,则此属性既可以在非static类型的方法中使用,也可以在static类型的方法中使用。但用static类型的方法不能访问非static类型的属性。

  4) 静态代码块

   一个类可以使用不包含在任何方法体中的静态代码块,当类被载入时,静态代码块被执行,且只执行一次,静态代码块经常用来进行类属性的初始化。如下面的程序代码所示:

class Person
{
	public Person()
	{
		System.out.println("1.public Person()");
	}
	// 此段代码会首先被执行
	static
	{
		System.out.println("2.Person类的静态代码块被调用!");
	}
}

public class TestStaticDemo5 {
	// 运行本程序时,静态代码块会被自动执行
	static
	{
		System.out.println("3.TestStaticDemo5类的静态代码块被调用!");
	}

	public static void main(String[] args) 
	{
		System.out.println("4.程序开始执行!");
		// 产生两个实例化对象
		new Person() ;
		new Person() ;
	}
}

      执行结果如下:

3.TestStaticDemo5类的静态代码块被调用!
4.程序开始执行!
2.Person类的静态代码块被调用!
1.public Person()
1.public Person()

• 内部类

  外部类是无法找到内部类中所声明的属性;而内部类则可以访问外部类的属性。外部类的对象可实例化一内部类的对象。如:

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display() ;

   内部类不仅可以在类中定义,也可以在方法中定义内部类。

• Javadoc标记



• 类的继承


    1) 在java中只允许单继承,而不允许多重继承,也就是说一个子类只能有一个父类,但是java中却允许多层继承

    2) 子类对象在实例化时会默认先去调用父类中的无参构造方法,之后再调用本类中的相应构造方法;

    3) 如果程序中指定了构造方法,则默认无参构造方法不会再生成;

    4) 用super(实参列表)调用父类中的构造方法,只能放在方法的第一行

    5) super也可用于调用父类中的属性或方法

        super.父类中的属性 ;
        super.父类中的方法() ;

    6) 子类在继承父类时,会继承父类中的全部的属性与方法;但子类不能显示地访问父类中的private属性和方法。

    7) 复写

        a) “复写”的概念与“重载”相似,它们均是Java“多态”的技术之一,所谓“重载”,即是方法名称相同,但却可在不同的场合做不同的事。当一个子类继承一父类,而子类中的方法与父类中的方法的名称,参数个数、类型都完全一致时,就称子类中的这个方法复写了父类中的方法。同理,如果子类中重复定义了父类中已有的属性,则称此子类中的属性复写了父类中的属性;

        b) 子类对象在调用复写的方法时,实际上调用的是子类中被复写好了的方法;
        c) 子类复写父类中的方法时,被子类复写的方法不能拥有比父类中更严格的访问权限;

        d) 子类可以通过super.方法()的方式调用父类中被子类复写的方法;

    8) this与super的比较


   

• 抽象类

     抽象类的作用有点类似“模版”,其目的是要设计者依据它的格式来修改并创建新的类。但是并不能直接由抽象类创建对象,只能通过抽象类派生出新的类,再由它来创建对象。
     抽象类定义规则:
     1) 抽象类和抽象方法都必须用abstract关键字来修饰;
     2) 抽象类不能被实例化,也就是不能用new关键字去产生对象;
     3) 抽象方法只需声明,而不需实现;
     4) 含有抽象方法的类必须被声明为抽象类,抽象类的子类必须复写所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。


     5) 抽象类也可以像普通类一样,有构造方法、一般方法、属性,更重要的是还可以有一些抽象方法,留给子类去实现,而且在抽象类中声明构造方法后,在子类中必须明确调用

• final关键字

    在Java中声明类、属性和方法时,可使用关键字final来修饰。
    1) final标记的能被继承
    2) final标记的方法能被子类复写
    3) final标记的变量(成员变量或局部变量)即为常量,只能赋值一次。

• 接口(interface)

   接口(interface)是Java所提供的另一种重要技术,它的结构和抽象类非常相似,也具有数据成员与抽象方法,但它与抽象类又有以下两点不同:
   1) 接口里的数据成员必须初始化,且数据成员均为常量
   2) 接口里的方法必须全部声明为abstract,也就是说,接口不能像抽象类一样保有一般的方法,而必须全部是“抽象方法”。
   接口定义的语法如下:



     接口与一般类一样,本身也具有数据成员与方法,但数据成员一定要赋初值,且此值将不能再更改,方法也必须是“抽象方法”。也正因为方法必须是抽象方法,而没有一般的方法,所以抽象方法声明的关键字abstract是可以省略的。相同的情况也发生在数据成员身上,因数据成员必须赋初值,且此值不能再被更改,所以声明数据成员的关键字final也可省略。
     事实上只要记得:(1)接口里的“抽象方法”只要做声明即可,而不用定义其处理的方式;(2)数据成员必须赋初值,这样就可以了。

• 接口实现(implements)

  每一个由接口实现的类必须在类内部复写接口中的抽象方法,且可自由地使用接口中的常量。



• 接口与抽象类的区别

      接口是java实现多继承的一种机制,一个类只能继承一个父类,但如果需要一个类继承多个抽象方法的话,就明显无法实现,所以就出现了接口的概念。一个类只可以继承一个父类,但却可以实现多个接口。
      接口与一般类一样,均可通过扩展的技术来派生出新的接口。原来的接口称为基本接口或父接口,派生出的接口称为派生接口或子接口。通过这种机制,派生接口不仅可以保留父接口的成员,同时也可加入新的成员以满足实际的需要。

      同样的,接口的扩展(或继承)也是通过关键字extends来实现的。有趣的是,一个接口可以继承多个接口,这点与类的继承有所不同。


• 对象多态性

   1) 向上转型(实例本身是子类):
       •父类对象通过子类对象去实例化,实际上就是对象的向上转型。向上转型是不需要进行强制类型转换的,但是向上转型会丢失精度。
       •向上转型可以自动完成;

   2) 向下转型(实例本身是子类):
       •与向上转型对应的一个概念就是“向下转型”,所谓向下转型,也就是说父类的对象可以转换为子类对象,但是需要注意的是,这时则必须要进行强制的类型转换。
       •向下转型必须进行强制类型转换。

   调用的属性和方法为实例本身的属性和方法

• Object类

   Java中有一个比较特殊的类,就是Object类,它是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类就默认继承Object类。因此,Object类是Java类层中的最高层类,是所有类的超类。换句话说,Java中任何一个类都是它的子类。由于所有的类都是由Object类衍生出来的,所以Object类中的方法适用于所有类。

package java.lang;

/**
 * The root class of the Java class hierarchy. All non-primitive types
 * (including arrays) inherit either directly or indirectly from this class.
 */
public class Object {
    /**
     * Constructs a new instance of {@code Object}.
     */
    public Object() {
    }

    protected Object clone() throws CloneNotSupportedException {
        if (!(this instanceof Cloneable)) {
            throw new CloneNotSupportedException("Class doesn't implement Cloneable");
        }

        return internalClone((Cloneable) this);
    }

    /*
     * Native helper method for cloning.
     */
    private native Object internalClone(Cloneable o);

    /**
     * Compares this instance with the specified object and indicates if they
     * are equal. In order to be equal, {@code o} must represent the same object
     * as this instance using a class-specific comparison. The general contract
     * is that this comparison should be reflexive, symmetric, and transitive.
     * Also, no object reference other than null is equal to null.
     */
    public boolean equals(Object o) {
        return this == o;
    }

    /**
     * Invoked when the garbage collector has detected that this instance is no longer reachable.
     * The default implementation does nothing, but this method can be overridden to free resources.
     */
    @FindBugsSuppressWarnings("FI_EMPTY")
    protected void finalize() throws Throwable {
    }

    /**
     * Returns the unique instance of {@link Class} that represents this
     * object's class. Note that {@code getClass()} is a special case in that it
     * actually returns {@code Class<? extends Foo>} where {@code Foo} is the
     * erasure of the type of the expression {@code getClass()} was called upon.
     */
    public final native Class<?> getClass();

    /**
     * Returns an integer hash code for this object. By contract, any two
     * objects for which {@link #equals} returns {@code true} must return
     * the same hash code value. This means that subclasses of {@code Object}
     * usually override both methods or neither method.
     */
    public native int hashCode();

    /**
     * Causes a thread which is waiting on this object's monitor (by means of
     * calling one of the {@code wait()} methods) to be woken up. If more than
     * one thread is waiting, one of them is chosen at the discretion of the
     * VM. The chosen thread will not run immediately. The thread
     * that called {@code notify()} has to release the object's monitor first.
     * Also, the chosen thread still has to compete against other threads that
     * try to synchronize on the same object.
     */
    public final native void notify();

    /**
     * Causes all threads which are waiting on this object's monitor (by means
     * of calling one of the {@code wait()} methods) to be woken up. The threads
     * will not run immediately. The thread that called {@code notify()} has to
     * release the object's monitor first. Also, the threads still have to
     * compete against other threads that try to synchronize on the same object.
     */
    public final native void notifyAll();

    /**
     * Returns a string containing a concise, human-readable description of this
     * object. Subclasses are encouraged to override this method and provide an
     * implementation that takes into account the object's type and data. The
     * default implementation is equivalent to the following expression:
     */
    public String toString() {
        return getClass().getName() + '@' + Integer.toHexString(hashCode());
    }

    /**
     * Causes the calling thread to wait until another thread calls the {@code
     * notify()} or {@code notifyAll()} method of this object. This method can
     * only be invoked by a thread which owns this object's monitor; see
     * {@link #notify()} on how a thread can become the owner of a monitor.
     */
    public final void wait() throws InterruptedException {
        wait(0 ,0);
    }

    /**
     * Causes the calling thread to wait until another thread calls the {@code
     * notify()} or {@code notifyAll()} method of this object or until the
     * specified timeout expires. This method can only be invoked by a thread
     * which owns this object's monitor; see {@link #notify()} on how a thread
     * can become the owner of a monitor.
     */
    public final void wait(long millis) throws InterruptedException {
        wait(millis, 0);
    }

    /**
     * Causes the calling thread to wait until another thread calls the {@code
     * notify()} or {@code notifyAll()} method of this object or until the
     * specified timeout expires. This method can only be invoked by a thread
     * that owns this object's monitor; see {@link #notify()} on how a thread
     * can become the owner of a monitor.
     */
    public final native void wait(long millis, int nanos) throws InterruptedException;
}

   1) toString方法

   Object类的方法中有一个toString()方法,此方法是在打印对象时被调用的。
   如: Person p = new Person();
        System.out.println(p); // 实质上调用Person.toString方法,所以在Person中需要复写toString方法。它相当于:System.out.println(p.toString());

   2) equals方法

   Object中的equals用于比较两个对象地址是否相同;如果需要用于比较两个对象内容是否相同,则需要复写。

• 匿名内部类

  接口不用声明实质上的类,就可以使用。


interface A
{
    public void fun1() ;
}

class B
{
    int i = 10 ;
    public void get(A a)
    {
        a.fun1() ;
    }
    
    public void test()
    {
        this.get(new A()  //匿名内部类
                {
                    public void fun1()
                    {
                        System.out.println(i) ;
                    }
                }
        );
    }
}

• 小结

1) 通过extends关键字,可将父类的成员(包含数据成员与方法)继承到子类。
2) Java在执行子类的构造方法之前,会先调用父类中无参的构造方法,其目的是为了对继承自父类的成员做初始化的操作。
3) 父类有数个构造方法时,如要调用特定的构造方法,则可在子类的构造方法中,通过super()这个关键字来完成。
4) this()是在同一类内调用其它的构造方法,而super()则是从子类的构造方法调用其父类的构造方法。
5) this()除了可用来调用同一类内的其它构造方法之外,如果同一类内“实例变量”与局部(local)变量的名称相同时,也可利用它来调用同一类内的“实例变量”。
6) this()与super()其相似之处:(1)当构造方法有重载时,两者均会根据所给予的参数的类型与个数,正确地执行相对应的构造方法。(2)两者均必须编写在构造方法内的第一行,也正是这个原因,this()与super()无法同时存在同一个构造方法内。
7) “重载”(overloading),它是指在相同类内,定义名称相同,但参数个数或类型不同的方法,因此Java便可依据参数的个数或类型调用相应的方法。
8) “复写”(overriding),它是在子类当中,定义名称、参数个数与类型均与父类相同的方法,用以复写父类中的方法。
9) 如果父类的方法不希望子类的方法来复写它,可在父类的方法之前加上“final”关键字,如此该方法便不会被复写。
10) final的另一个功用是把它加在数据成员变量前面,如此该变量就变成了一个常量(constant),如此便无法在程序代码中再做修改了。
11) 所有的类均继承自Object类。
12) 复写Object类中的equals() method可用来比较两个类的对象是否相等。
13) Java可以创建抽象类,专门用来当做父类。抽象类的作用类似于“模板”,其目的是依据其格式来修改并创建新的类。
14) 抽象类的方法可分为两种:一种是一般的方法,另一种是以abstract关键字开头的“抽象方法”。“抽象方法”并没有定义方法体,而是要保留给由抽象类派生出的新类来定义。
15) 利用父类的变量数组来访问子类的内容的较好的做法是:
    (1) 先创建父类的变量数组;
    (2) 利用数组元素创建子类的对象,并以它来访问子类的内容。
16) 抽象类不能直接用来产生对象。
17) 接口的结构和抽象类非常相似,它也具有数据成员与抽象method,但它与抽象类有两点不同:

      (1) 接口的数据成员必须初始化。

      (2)接口里的方法必须全部都声明成abstract。
18) 利用接口的特性来打造一个新的类,称为接口的实现(implementation)。
19) Java并不允许多重继承。
20) 接口与一般类一样,均可通过扩展的技术来派生出新的接口。原来的接口称为基本接口或父接口;派生出的接口成为派生接口或子接口。通过这种机制,派生接口不仅可以保留父接口的成员,同时也可以加入新的成员以满足实际的需要。
21) Java对象的多态性分为:向上转型(自动))向下转型(强制)。
22) 通过instanceof关键字,可以判断对象属于那个类。
23) 匿名内部类(anonymous inner class)的好处是可利用内部类创建不具有名称的对象,并利用它访问到类里的成员。

• 异常处理

    几种常见的异常:
    1) 算术异常(ArithmeticException);
    2) 没有给对象开辟内存空间时会出现空指针异常(NullPointerException);
    3) 找不到文件异常(FileNotFoundException)。

    在没有异常处理的语言中,就必须使用if或switch等语句,配合所想得到的错误状况来捕捉程序里所有可能发生的错误。但为了捕捉这些错误,编写出来的程序代码经常有很多的if语句,有时候这样也未必能捕捉到所有的错误,而且这样做势必导致程序运行效率的降低。

    Java的异常处理机制恰好改进了这一点。它具有易于使用、可自行定义异常类,处理抛出的异常同时又不会降低程序运行的速度等优点。因而在Java程序设计时,应充分地利用Java的异常处理机制,以增进程序的稳定性及效率。


     • 值得一提的是,finally块是可以省略的。如果省略了finally块不写,则在catch()块运行结束后,程序跳到try-cath块之后继续执行。

• 异常类的继承架构


      习惯上将Error与Exception类统称为异常类,但这两者本质上还是有不同的。Error类专门用来处理严重影响程序运行的错误,可是通常程序设计者不会设计程序代码去捕捉这种错误,其原因在于即使捕捉到它,也无法给予适当的处理,如JAVA虚拟机出错就属于一种Error。
      不同于Error类,Exception类包含了一般性的异常,这些异常通常在捕捉到之后便可做妥善的处理,以确保程序继续运行。
      IOException一定要编写异常处理的程序代码才行,它通常用来处理与输入/输出相关的操作,如文件的访问、网络的连接等。

• 抛出异常

  1) 在程序中抛出异常
      throw 异常类实例对象;

      如:throw new ArithmeticException("一个算术异常");

  2) 指定方法抛出异常
      如果由方法会抛出异常,则可将处理此异常的try-catch-finally块写在调用此方法的程序代码内。此方法的定义方式如下:
      方法名称(参数…) throws 异常类1,异常类2,…

     如:void add(int a,int b) throws Exception { }

• 自定义异常类

 

   Exception构造方法:public Exception(String message)

• 小结

1) 程序中没有处理异常代码时,Java的默认异常处理机制会做下面的操作:
    (1) 抛出异常。
    (2) 停止程序运行。
2) 异常处理是由try、catch与finally三个关键字所组成的程序块,其语法请参考格式7-1。
3) try程序块中若有异常发生时,程序的运行便会中断,抛出“由系统类所产生的对象”,并依下列的步骤来运行:
    (1) 抛出的对象如果属于catch()括号内所要捕捉的异常类,catch会捕捉此异常,然后进到catch程序块里继续执行。
    (2)无论try程序块是否捕捉到异常,也不管捕捉到的异常是否与catch()括号里的异常相同,最后都会运行finally块里的程序代码。
    (3) finally中的代码是异常的统一出口,无论是否发生异常都会执行此段代码。
4) 当异常发生时,有两种处理方式:
    (1)交由Java默认的异常处理机制去处理。
    (2)自行编写try-catch-finally块来捕捉异常。
5) 异常可分为两大类:java.lang.Exception与java.lang.Error类。
6) RuntimeException可以不编写异常处理的程序代码,依然可以编译成功,它是在程序运行时才有可能发生的;而其它的Exception一定要编写异常处理的程序代码才能使程序通过编译。
7) catch()括号内,只接收由Throwable类的子类所产生的对象,其它的类均不接收。
8) 抛出异常有下列两种方式:
    (1)在程序中抛出异常。
    (2)指定方法抛出异常。
9) 程序中抛出异常时,要用到throw这个关键字。
10) 如果方法会抛出异常(使用throws),则可将处理此异常的try-catch-finally块写在调用此方法的程序代码中


• 包及访问权限

• 包的概念及使用

   package是在使用多个类或接口时,为了避免名称重复而采用的一种措施;经过package的声明之后,在同一文件内的接口或类都被纳入相同的package中。其使用语法如下:
   package 包名称;
   如:package my.test;

          编译方法:javac -d . HelloWorld.java

          执行方法:java my.test.HelloWorld

• import语句的使用

   若要访问不同package内某个public类的成员时,在程序代码内必须明确地指明“被访问package的名称.类名称”。其使用语法如下:
   import package名称.类名称;

   import package名称.*;则导入包中所有的类。在Java中,导入全部类或是导入指定的类,对于程序的性能是没有影响的,所以在开发中可以直接写导入全部类会比较方便。

• JDK中常见的包

   SUN公司在JDK中为程序开发者提供了各种实用类,这些类按功能不同分别被放入了不同的包中,供开发者使用,下面简要介绍其中最常用的几个包:

   1) java.lang — 包含一些Java语言的核心类,如String、Math、Integer、System和Thread,提供常用功能。在java.lang包中还有一个子包:java.lang.reflect用于实现java类的反射机制。
   2) java.awt — 包含了构成抽象窗口工具集(abstract window toolkits)的多个类,这些类被用来构建和管理应用程序的图形用户界面(GUI)。
   3)  javax.swing — 此包用于建立图形用户界面,此包中的组件相对于java.awt包而言是轻量级组件。
   4)  java.applet — 包含applet运行所需的一些类。
   5)  java.net — 包含执行与网络相关的操作的类。
   6)  java.io — 包含能提供多种输入/输出功能的类。
   7)  java.util — 包含一些实用工具类,如定义系统特性、与日期日历相关的函数。

   注意:java1.2以后的版本中,java.lang这个包会自动被导入,对于其中的类,不需要使用import语句来做导入了,如前面经常使用的System类。

• 类成员的访问控制权限

   在JAVA中有四种访问控制权限,分别为:private、default、protected、public。
   1) private访问控制符
      如果一个成员方法或成员变量名前使用了private访问控制符,那么这个成员只能在这个类的内部使用。
      注意:不能在方法体内声明的变量前加private修饰符。

   2) default访问控制符
       如果一个成员方法或成员变量名前没有使用任何访问控制符,就称这个成员所拥有的是默认的(default)访问控制符。默认的访问控制成员可以被这个包中的其它类访问。如果一个子类与其父类位于不同的包中,子类也不能访问父类中的默认访问控制成员。

   3) protected访问控制符
        如果一个成员方法或成员变量名前使用了protected访问控制符,那么这个成员既可以被同一个包中的其它类访问,也可以被不同包中的子类访问。

   4) public访问控制符
         如果一个成员方法或成员变量名前使用了public访问控制符,那么这个成员可以被所有的类访问,不管访问类与被访问类是否在同一个包中。

• Java的命名习惯

  1) 包名:包名中的字母一律小写,如:demo.java。
  2) 类名、接口名:应当使用名词,每个单词的首字母大写,如:TestPerson。
  3) 方法名:第一个单词小写,后面每个单词的首字母大写,如:talkMySelf。
  4) 常量名:每个字母一律大写,如:COUNTRY。

• Jar文件的使用

    开发者用的JDK中的包和类主要在JDK的安装目录下的jre\lib\rt.jar文件中,由于Java虚拟机会自动找到这个jar包,所以在开发中使用这个jar包的类时,无需再用classpath来指向它们的位置了。
     jar文件就是Java Archive File,而它的应用是与Java息息相关的。jar文件就是一种压缩文件,与常见的ZIP压缩文件格式兼容,习惯上称之为jar包。如果开发者开发了许多类,当需要把这些类提供给用户使用时,通常都会将这些类压缩到一个jar文件中,以jar包的方式提供给用户使用。只要别人的classpath环境变量的设置中包含这个jar文件,Java虚拟机就能自动在内存中解压这个jar文件,把这个jar文件当作一个目录,在这个jar文件中去寻找所需要的类及包名所对应的目录结构。

    生成.jar文件:

     jar –cvf create.jar demo
     · -c:创建新的存档
     ·-v:生成详细输出到标准输出上
     · -f:指定存档文件名
     · create.jar:是生成jar文件的名称
     · demo:要打成jar文件的包

    举例如下:

     在HelloWorld (jerry.test)中需要import danny.test.Person和danny.test.Student

      1) javac -d . Person.java Student.java

      2) jar -cvf danny.jar danny

      3) set classpath=%classpath%;D:\Java\danny.jar

      4) echo %classpath%

      5) javac -d . HelloWorld.java

      6) java jerry.test.HelloWorld    

•  小结

    1) java中使用包可以实现多人协作的开发模式。
    2) 在java中使用package关键字来将一个类放入一个包中。
    3) 在java中使用import语句,可以导入一个已有的包。
    4) java中的访问控制权限分为四种:private、default、protected、public。
    5) 使用jar命令可以将一个包打成一个jar文件,供用户使用。

• 多线程

• 通过继承Thread类实现多线程  

 如果在类里要激活线程,必须先做好下面两个准备:
     1) 线程必须扩展自Thread类,使自己成为它的子类;
     2) 线程的处理必须编写在run()方法内。


     3) 启动线程:new 类名称().start();

     如:class MyThread extends Thread { }

            new MyThread().start();

• 通过实现Runnable接口实现多线程

   JAVA程序只允许单一继承,即一个子类只能有一个父类,所以在Java中如果一个类继承了某一个类,同时又想采用多线程技术的时,就不能用Thread类产生线程,因为Java不允许多继承,这时就要用Runnable接口来创建线程了。


     如:class MyThread implements Runnable { }

            MyThread p = new MyThread();
            new Thread(p).start();

• 两种多线程实现机制的比较

   实现Runnable接口相对于继承Thread类来说,有如下显著的优势:
   (1) 适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码、数据有效分离,较好地体现了面向对象的设计思想。
   (2) 可以避免由于Java的单继承特性带来的局限。开发中经常碰到这样一种情况,即:当要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么就只能采用实现Runnable接口的方式了。
   (3) 增强了程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程可以操作相同的数据,与它们的代码无关。当共享访问相同的对象时,即共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去,这个对象就是一个实现了Runnable接口的类的实例。
   事实上,几乎所有多线程应用都可用第二种方式,即实现Runnable接口。

• 线程操作的一些方法



• 后台线程与setDaemon()方法

   对Java程序来说,只要还有一个前台线程在运行,这个进程就不会结束,如果一个进程中只有后台线程在运行,这个进程就会结束。前台线程是相对后台线程而言的,前面所介绍的线程都是前台线程。那么什么样的线程是后台线程呢?如果某个线程对象在启动(调用start()方法)之前调用了setDaemon(true)方法,这个线程就变成了后台线程。

• 线程的强制运行

   MyThread.join:直到MyThread线程执行完之后,才执行后面的代码。

• 线程的休眠

   Thread.sleep(ms)或Thread.sleep(ms,ns)

 线程的中断

   当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它。也可以用Thread对象调用isInterrupted()方法来检查每个线程的中断状态。Thread.sleep抛出中断异常之后,会清除中断标记;否则中断标记一直存在。

• 多线程的同步

• 同步代码块

   在同一时刻只能有一个线程可以进入同步代码块内运行,只有当该线程离开同步代码块后,其它线程才能进入同步代码块内运行。


• 同步方法

   除了可以对代码块进行同步外,也可以对函数实现同步,只要在需要同步的函数定义前加上synchronized关键字即可。


   在同一类中,使用synchronized关键字定义的若干方法,可以在多个线程之间同步,当有一个线程进入了有synchronized修饰的方法时,其它线程就不能进入同一个对象使用synchronized来修饰的所有方法,直到第一个线程执行完它所进入的synchronized修饰的方法为止。

• 线程间通讯

  Java是通过Object类的wait、notify、notifyAll这几个方法来实现线程间的通信的,又因为所有的类都是从Object继承的,所以任何类都可以直接使用这些方法。下面是这三个方法的简要说明:
   • wait:告诉当前线程放弃监视器并进入睡眠状态,直到其它线程进入同一监视器并调用notify为止。
   • notify:唤醒同一对象监视器中调用wait的第一个线程。类似排队买票,一个人买完之后,后面的人可以继续买。
   • notifyAll:唤醒同一对象监视器中调用wait的所有线程,具有最高优先级的线程首先被唤醒并执行。

   wait、notify、notifyAll这三个方法只能在synchronized方法中调用,即无论线程调用一个对象的wait还是notify方法,该线程必须先得到该对象的锁标记,这样,notify只能唤醒同一对象监视器中调用wait的线程,使用多个对象监视器,就可以分别有多个wait、notify的情况,同组里的wait只能被同组的notify唤醒。
   一个线程的等待和唤醒过程可以用下图表示:


• 线程生命周期的控制


     控制线程生命周期的方法有很多种,如:suspend方法、resume方法和stop方法。但这三个方法都不推荐使用,其中,不推荐使用suspend和resume的原因是:
     (1) 会导致死锁的发生。
     (2) 它允许一个线程(甲)通过直接控制另外一个线程(乙)的代码来直接控制那个线程(乙)。
     虽然stop能够避免死锁的发生,但是也有其它的不足:如果一个线程正在操作共享数据段,操作过程没有完成就被“stop”了的话,将会导致数据的不完整性。因此stop方法也不提倡使用了!

     控制线程生命周期的可用方法如下:

     (1) 通过控制run方法中循环条件的方式来结束一个线程的方法是推荐读者使用的,这也是实际中用的最多的方法。

• 小结

1、线程(thread)是指程序的运行流程。“多线程”的机制可以同时运行多个程序块,使程序运行的效率更高,也解决了传统程序设计语言所无法解决的问题。
2、如果在类里要激活线程,必须先做好下面两项准备:
(1)、此类必须是扩展自Thread类,使自己成为它的子类。
(2)、线程的处理必须编写在run()方法内。
3、run()方法是定义在Thread类里的一个方法,因此把线程的程序代码编写在run()方法内,所做的就是覆盖的操作。
4、Runnable接口里声明了抽象的run()方法,因此必须在实现Runnable接口的类里明确定义run()方法。
5、每一个线程,在其创建和消亡之前,均会处于下列五种状态之一:创建、就绪、运行、阻塞、终止。
6、暂停状态的线程可由下列的情况所产生:
(1)该线程调用对象的wait()时。
(2)该线程本身调用sleep()时。
(3)该线程和另一个线程join()在一起时。
7、被冻结因素消失的原因有:
(1)如果线程是由调用对象的wait()方法所冻结,则该对象的notify()方法被调用时可解除冻结。
(2)线程进入休眠(sleep)状态,但指定的休眠时间到了。
8、当线程的run()方法运行结束,或是由线程调用它的stop()方法时,则线程进入消亡状态。
9、Thread类里的sleep()方法可用来控制线程的休眠状态,休眠的时间要视sleep()里的参数而定。
10、要强制某一线程运行,可用join()方法。
11、join()方法会抛出InterruptedException的异常,所以编写时必须把join()方法编写在try-catch块内。
12、当多个线程对象操纵同一共享资源时,要使用synchronized关键字来进行资源的同步处理。

• 文件(IO)操作

   JAVA语言定义了许多类专门负责各种方式的输入输出,这些类都被放在java.io包中。

•  File类

    File类是IO包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操纵文件,通过调用File类提供的各种方法,能够完成创建、删除文件,重命名文件,判断文件的读写权限及是否存在,设置和查询文件的最近修改时间等操作。
   Java 能正确处理UNIX和Windows/DOS约定路径分隔符。如果在Windows版本的Java下用斜线(/),路径处理依然正确。记住,如果使用Windows/DOS使用反斜线(\)的约定,就需要在字符串内使用它的转义序列(\\)。Java约定是用UNIX和URL风格的斜线来作路径分隔符。
   下面的构造方法可以用来生成File 对象:
     new File(String directoryPath)
   这里,directoryPath是文件的路径名。

• RandomAccessFile类

  RandomAccessFile对象类有个位置指示器,指向当前读写处的位置,当读写n个字节后,文件指示器将指向这n个字节后的下一个字节处。刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写操作将从新的位置开始。

public RandomAccessFile(File file, String mode) throws FileNotFoundException
/*
mode:
    "r":只读
    "rw":读写
    "rws":每次write时,同步文件和metadata
    "rwd":每次write时,同步文件而不同步metadata
*/

• 字节流(byte)

   Java 的流式输入/输出建立在四个抽象类的基础上:InputStream, OutputStream, Reader和Writer。它们用来创建具体流式子类。尽管程序通过具体子类执行输入/输出操作,但顶层的类定义了所有流类的基本通用功能。

   InputStream 和OutputStream:设计成字节流类

   Reader 和Writer :为字符流设计。

   字节流类和字符流类形成分离的层次结构。一般说来,处理字符或字符串时应使用字符流类,处理字节或二进制对象时应用字节流类。
    一般在操作文件流时,不管是字节流还是字符流都可以按照以下的方式进行:
    1) 使用File类找到一个文件
    2) 通过File类的对象去实例化字节流或字符流的子类
    3) 进行字节(字符)的读、写操作
    4) 关闭文件流

• InputStream(输入字节流,抽象类)

   InputStream 是一个定义了Java流式字节输入模式的抽象类。该类的所有方法在出错条件下都会引发一个IOException 异常。下表显示了InputStream的方法:
   public abstract class InputStream extends Object implements Closeable 


• OutputStream(输出字节流,抽象类)

   OutputStream是定义了流式字节输出模式的抽象类。该类的所有方法返回一个void 值并且在出错情况下引发一个IOException异常。

  

•  FileInputStream(文件输入流,非抽象类)

    FileInputStream 类创建一个能从文件读取字节的InputStream 类,它的两个常用的构造方法如下:
      FileInputStream(String filepath)
      FileInputStream(File fileObj)

• FileOutputStream(文件输出流,非抽象类)

   FileOutputStream 创建了一个可以向文件写入字节的类OutputStream,它常用的构造方法如下:
     FileOutputStream(String filePath)
     FileOutputStream(File fileObj)
     FileOutputStream(String filePath, boolean append)


• 字符流(char)

  尽管字节流提供了处理任何类型输入/输出操作的足够的功能,但它们不能直接操作Unicode字符。既然Java的一个主要目标是支持“一次编写,处处运行”,包含直接的字符输入/输出的支持是必要的。

• Reader

  Reader是定义Java的流式字符输入模式的抽象类。该类的所有方法在出错情况下都将引发IOException 异常。


• Writer
  Writer 是定义流式字符输出的抽象类。所有该类的方法都返回一个void 值并在出错条件下引发IOException 异常。


FileReader

  FileReader类创建了一个可以读取文件内容的Reader类。它最常用的构造方法显示如下:
    FileReader(String filePath)
    FileReader(File fileObj)

  每一个都能引发一个FileNotFoundException异常。这里,filePath是一个文件的完整路径,fileObj是描述该文件的File 对象。

• FileWriter

  FileWriter 创建一个可以写文件的Writer 类。它最常用的构造方法如下:
     FileWriter(String filePath)
     FileWriter(String filePath, boolean append)
     FileWriter(File fileObj)

  它们可以引发IOException或SecurityException异常。这里,filePath是文件的绝对路径,fileObj是描述该文件的File对象。如果append为true,输出是附加到文件尾的。FileWriter类的创建不依赖于文件存在与否。在创建文件之前,FileWriter将在创建对象时打开它来作为输出。如果试图打开一个只读文件,将引发一个IOException异常。

• 管道流

   管道流主要作用是可以连接两个线程间的通信。管道流也分为字节流(PipedInputStream、PipedOutputStream)与字符流(PipedReader、PipedWriter)两种类型,下面主要讲解PipedInputStream与PipedOutputStream。

   一个PipedInputStream对象必须和一个PipedOutputStream对象进行连接而产生一个通信管道,PipedOutputStream可以向管道中写入数据,PipedInputStream可以从管道中读取PipedOutputStream写入的数据。如下图所示,这两个类主要用来完成线程之间的通信,一个线程的PipedInputStream对象能够从另外一个线程的PipedOutputStream对象中读取数据。



•  ByteArrayInputStream与ByteArrayOutputStream (byte)

    ByteArrayInputStream是输入流的一种实现,它有两个构造函数,每个构造函数都需要一个字节数组来作为其数据源:
      ByteArrayInputStream(byte[ ] buf)
      ByteArrayInputStream(byte[ ] buf,int offset , int length)
      ByteArrayOutputStream()
      BuyteArrayoutputStream(int)

     如果程序在运行过程中要产生一些临时文件,可以采用虚拟文件方式实现,JDK中提供了ByteArrayInputStream和ByteArrayOutputStream两个类可实现类似于内存虚拟文件的功能。

• System.in和System.out

   为了支持标准输入输出设备,Java定义了两个特殊的流对象:System.in和System.out。System.in对应键盘,是InputStream类型的,程序使用System.in可以读取从键盘上输入的数据;System.out对应显示器,是PrintStream类型的,PrintStream是OutputStream的一个子类,程序使用System.out可以将数据输出到显示器上。键盘可以被当作一个特殊的输入流,显示器可以被当作一个特殊的输出流。

• 打印流

   PrintStream类提供了一系列的print和println方法,可以实现将基本数据类型的格式转化成字符串输出。在前面的程序中大量用到“System.out.println”语句中的System.out就是PrintStream类的一个实例对象。PrintStream有下面几个构造方法:
    PrintStream(OutputStream out)
    PrintStream(OutputStream out,boolean auotflush)
    PrintStream(OutputStream out,boolean auotflush, String encoding)

   其中autoflush控制在Java中遇到换行符(\n)时是否自动清空缓冲区,encoding是指定编码方式。println方法与print方法的区别是:前者会在打印完的内容后再多打印一个换行符(\n),所以println()等于print("\n")。

  Java的PrintStream对象具有多个重载的print和println方法,它们可输出各种类型(包括Object)的数据。对于基本数据类型的数据,print和println方法会先将它们转换成字符串的形式然后再输出,而不是输出原始的字节内容,如:整数221的打印结果是字符‘2’、‘2’、‘1’所组合成的一个字符串,而不是整数221在内存中的原始字节数据。对于一个非基本数据类型的对象,print和println方法会先调用对象的toString方法,然后再输出toString方法所返回的字符串。

• DataInputStream与DataOutputStream

   DataInputStream与DataOutputStream提供了与平台无关的数据操作,通常会先通过DataOutputStream按照一定的格式输出,再通过DataInputStream按照一定格式读入。由于可以得到java的各种基本类型甚至字符串,这样对得到的数据便可以方便地进行处理,这在通过协议传输的信息的网络上是非常适用的。

• 合并流

  采用SequenceInputStream类,可以实现两个文件的合并操作。

• 字节流与字符流的转换

  Java支持字节流和字符流,但有时需要字节流和字符流之间的转换。

  InputStreamReader和OutputStreamWriter,这两个类是字节流和字符流之间转换的类,InputStreamReader可以将一个字节流中的字节解码成字符,OuputStreamWriter将写入的字符编码成字节后写入一个字节流。
  • InputStreamReader有两个主要的构造函数:
        1) InputStreamReader(InputStream in) 

            // 用默认字符集创建一个InputStreamReader对象
        2) InputStreamReader(InputStream in,String CharsetName)
            // 接受已指定字符集名的字符串,并用该字符集创建对象

  • OutputStreamWriter也有对应的两个主要的构造函数:
        1) OutputStreamWriter(OutputStream in)
            // 用默认字符集创建一个OutputStreamWriter对象
        2) OutputStreamWriter(OutputStream in,String CharsetNarme)
            // 接受已指定字符集名的字符串,并用该字符集创建OutputStreamWriter对象
    为了达到最高的效率,避免频繁地进行字符与字节间的相互转换,最好不要直接使用这两个类来进行读写,应尽量使用BufferedWriter类包装OutputStreamWriter类,用BufferedReader类包装InputStreamReader类。例如:
    BufferedWriter out=new BufferedWriter(new OutputStreamWriter(System.out));
    BufferedReader in=new BufferedReader(new InputStreamReader(System.in));

• IO包中的类层次关系图

• 字节输入流(InputStream)



• 字节输出流(OutputStream)



• 字符输入流(Reader)



字符输出流(Writer)


• 字符编码

  Java中的字符使用的都是Unicode编码,Java技术在通过Unicode保证跨平台特性的前提下也支持了全扩展的本地平台字符集,而显示输出和键盘输入都是采用的本地编码。

• 对象序列化

   所谓的对象序列化(也叫串行化),是指将对象转换成二进制数据流的一种实现手段,通过将对象序列化,可以方便的实现对象的传输及保存。
   在Java中提供了ObjectInputStream与ObjectOutputStream这两个类用于序列化对象的操作。这两个类是用于存储和读取对象的输入输出流类,不难想象,只要把对象中的所有成员变量都存储起来,就等于保存了这个对象,之后从保存的对象之中再将对象读取进来就可以继续使用此对象。ObjectInputStream与ObjectOutputStream类,可以帮开发者完成保存和读取对象成员变量取值的过程,但要求读写或存储的对象必须实现了Serializable接口,但Serializable接口中没有定义任何方法,仅仅被用作一种标记,以被编译器作特殊处理。

import java.io.* ;
public class Person implements Serializable
{
    private String name ;
    private int age ;
    
    public Person(String name,int age)
    {
        this.name = name ;
        this.age = age ;
    }
    
    public String toString()
    {
        return " 姓名:"+this.name+",年龄:"+this.age ;
    }
};

public class SerializableDemo
{
    public static void main( String args[] ) throws Exception
    {
        File f = new File("SerializedPerson") ;
        serialize(f);
        deserialize(f);
    }

    // 以下方法为序列化对象方法
    public static void serialize(File f) throws Exception
    {
        OutputStream outputFile = new FileOutputStream(f);
        ObjectOutputStream cout = new ObjectOutputStream(outputFile);
        cout.writeObject(new Person("张三",25));
        cout.close();
    }
    // 以下方法为反序列化对象方法
    public static void deserialize(File f) throws Exception
    {
        InputStream inputFile = new FileInputStream(f);
        ObjectInputStream cin = new ObjectInputStream(inputFile);
        Person p = (Person) cin.readObject();
        System.out.println(p);
    }
}

    如果不希望类中的属性被序列化,可以在声明属性之前加上transient关键字。如下所示,下面的代码修改自前面所用到的Person.java程序,在声明属性时,前面多加了一个transient关键字。
    private transient String name ;
    private transient int age ;

• 小结

1、 Java中要进行IO操作,需要导入java.io包。
2、 Java中的File类是唯一操作磁盘文件的类。
3、 Java中的数据操作主要分为两种:
(1)、字节流(OutputStream、InputStream)(常用:FileOutputStream和FileInputStream)
(2)、字符流(Writer、Reader) (常用:FileWriter和FileReader)
这四个类都是抽象类,使用时,都必须依靠其子类实例化。
4、 Java定义了两个特殊的流对象:System.in和System.out。System.in对应键盘,是InputStream类型的,程序使用System.in可以读取从键盘上输入的数据;System.out对应显示器,可以向显示器上输出内容。
5、 InputStreamReader和OutputStreamWriter,这两个类是字节流和字符流之间转换的类,InputStreamReader可以将一个字节流中的字节解码成字符,OuputStreamWriter将写入的字符编码成字节后写入一个字节流。
6、一个类实现了Serializable接口之后,此类的对象可以被序列化,就表示可以保存在文件之中、或网络传输之中。如果不希望类中的某个属性被保存下来,可以用transient关键字声明属性。

• Java 常用类库

• String类和StringBuffer类

   一个字符串就是一连串的字符,字符串的处理在许多程序中都用得到。Java定义了String和StringBuffer两个类来封装对字符串的各种操作。它们都被放到了java.lang包中,不需要用import java.lang这个语句导入该包就可以直接使用它们。

   String类用于比较两个字符串、查找和抽取串中的字符或子串、字符串与其它类型之间的相互转换等。String类对象的内容一旦被初始化就不能再改变

   StringBuffer类用于内容可以改变的字符串,可以将其它各种类型的数据增加、插入到字符串中,也可以转置字符串中原来的内容。一旦通过StringBuffer生成了最终想要的字符串,就应该使用StringBuffer.toString方法将其转换成String类,随后,就可以使用String类的各种方法操纵这个字符串了。

  Java为字符串提供了特别的连接操作符(+),可以把其它各种类型的数据转换成字符串,并前后连接成新的字符串。连接操作符(+)的功能是通过StringBuffer类和它的append方法实现的。

   例如:
    String x = "a" + 4 + "c";
    编译时等效于
    String x=new StringBuffer().append("a").append(4).append("c").toString();

• 基本数据类型的包装类













• 

















转载于:https://my.oschina.net/abcijkxyz/blog/788933

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值