<1>create and destroy object
you must create your object
But can not destroy.
Is an object to hold other object .
Every class in Java is desendent of the class:Object
<2>引用 String s; Here is only a handle that refer to new!
String s=new String("a string");
1>An object of string is create.
2>The object is initalized w/"a string"..
3>A variable as handle to string is created.
4>The value of the handle variable is assign to the object.
类第一个字母有大写.
变量 、方法用小写.
翁凯java讲义概要(五)
<1>建立新的数据类型:class //命名规则
class ATypeName{
/* class body goes here*/
}
note:Method of Java 只能作为类的一部分创建
<2>方法,参数和返回值
returnType methodName(/*argument list*/)
{
/*Method body*/
}
note:C++有全局函数而Java没有
<3>赋值
当"from one object to another" 赋值实际上就是与句柄从一个地方复制到另一的地方.
case:Assignment.java
//Assignment.java
//Assignment with objects is a bit tricky
class Number{
int i;
}
public class Assignment{
public static void main(String args[]){
Number n1=new Number();
Number n2=new Number();
n1.i=9;
n2.i=57;
System.out.println("1:n1.i="+n1.i+",n2.i="+n2.i);
n1=n2;
System.out.println("2:n1.i="+n1.i+",n2.i="+n2.i);
n1.i=27;
System.out.println("3:n1.i="+n1.i+",n2.i="+n2.i);
}
}
<4>"+"连接字符串
将一个对象传递到到方法内部时也是赋值
参数传递方式(传值)
//Passing objects to methods can be bit tricky
Case:PassObject.java
//PassObject.java
//Passing objects to method can be a bit tricky
class Letter{
char c;
}
public class PassObject{
static void f(Letter y){
y.c='e';
}
public static void main(String args[]){
Letter x=new Letter();
x.c='a';
System.out.println("1:x.c="+x.c);
f(x);
System.out.println("2:x.c="+x.c);
}
}
Note:C,C++拷贝构造 而Java只有应用
“+”运算符可以用来连接字符串。
<5>关系运算符
关系运算符==和!=也只能对任何对象进行,但是它们的含义常常使人迷惑
Case:Equivalence.java
//Equivalence.java
public class Equivalence {
public static void main(String argsp[]){
Integer n1=new Integer(3);
Integer n2=new Integer(3);
System.out.println(n1==n2);
System.out.println(n1!=n2);
}
}
Note:n1是一个引用,n2也是个引用,只是指向的方向不同即地址不一样,引用的本质就是指针,是不可计算的
地址。
<6>Break and Continue
<7>初始化和清除
As the computer revolution progresses,"unsaffe"programming has become one of the maior culprits that makes programming expensive.
初始化和清除是程序设计安全性的两个重要问题
Note:C++为我们引用了构造函数的概念 Java也沿用了这个概念,但新增了自己的垃圾收集器。
<8>用构造函数自动初始化
如果某个类有一个构造函数,那么有创建对象的时候,Java会自动调用那个构造函数,构造函数的名字与类的名字相同。
//SimpleConstructor.java
//Demonstration of a simple constructor
class Rock{
Rock(){//This is a simple constructor
System.out.println("Creating Rock");
}
}
public class SimpleConstructor{
public static void main(String args[]){
for(int i=0;i<10;i++){
new Rock();
}
}
}
缺省构造函数没有参数,new Rock()一制造出来就是垃圾,因为它没有被引用。
<9>Methods overloading
One of the important features in any programming language is the use of names.
我们用名字引用或描述所有对象与方法。
在日常生活中我们用相同的词表达多种不同的含义,即词的“重载”。
大多数程序设计语言要为我们每个函数都设定一个独一无二的标志符,但是构造函数的出现
要求函数名也能够重载。
Often the same word expresses a number of different meanings--It's oveloaded.
每个重载方法都必须采取独一无二的自变量类型列表。
Note:如果一个类没有定义构造函数,则编译程序会帮助我们自动创建一个缺省构造函数。
然而一但定义了一个构造函数,就不会帮我们自动生成了。
<10>this
this关键字可以为已调用了其方法的那个对象重载生成相应的句柄。
//Leaf.java
//Simple use of the "this" keyword
public class Leaf{
private int i=0;
Leaf increment(){
i++;
return this;
}
void print(){
System.out.println("i="+i);
}
public static void main(String args[]){
Leaf x=new Leaf();
x.increment().increment().increment().print();
}
}
在一个构造函数中调用另一个构造函数时,用this关键字。
//Flower.java
//Calling constructors with "this"
public class Flower{
private int petalCount=0;
private String s=new String("null");
Flower(int petals){
petalCount=petals;
System.out.println(petalCount);
}
Flower(String ss){
System.out.println("Constructor String only");
s=ss;
}
Flower(String s,int petals){
this(petals);
//!this(s); Can't call two
this.s=s;
//Another use of "this"
System.out.println("String & int args");
}
public static void main(String args[]){
Flower f1=new Flower(1);
Flower f2=new Flower(2);
Flower f3=new Flower("test",3);
}
}
构造函数调用必须是构造函数中的第一条语句,并且不能在一个构造函数调用两个以上的构造函数。
<1>清除:收尾和垃圾收集
垃圾收集机制只知道怎样释放有new分配的内存,所以它不知道如何释放对象的"特殊"内存.
一旦垃圾收集机制准备释放对象占用的存储空间,它首先调用finalize().
但是finalize()和c++的析构函数截然不同:
1>垃圾收集不等于析构.
2>对象可能不会被当作垃圾被收集.
3>垃圾收集只跟内存有关.
<2>成员初始化
Java goes out of its way to guarantee that any variable is properly initlialized before it is used.
由于任何方法都可以初始化或使用那个数据,所以在正式使用数据前,若喊是强迫程序员将其一一初始化成一个适当的值,就可能不够实际,因此一个类的所有primitive数据数据成员都会保证获得一个缺省值,当然句柄会获得一个null值.
什么是null?
什么是句柄?
<3>定义初始化(在c++不允许)一个直接做法是在定义数据成员的同时为其赋值.
eg:class Measurement{
boolean b=ture;
char c='z';
Depth d=new Depth();
}
可以调用一个方法进行初始化
eg:class Clnit{
int i=f();
}
当然这个方法也可以使用参数
eg:class Clnit{
int i=f();
int k=g(i);
}
但是那些参数不能是尚未初始化的其他数据成员.
eg:class ClnitWrong{
int i=g(i);
int i=f();
}
<4>初始化的顺序
在一个类里,初始化的顺序是由变量在类内的定义顺序决定的,即使变量定义大量遍布于方法定义中间,那些变量仍然会在调用任何方法之前得到初始化--当然在构造函数之前.
<5>静态数据初始化
类class与对象(一个是规则一个是实体)
Everything is object.
静态数据成员总在这个类的第一个对象要创建的时候便初始化.
Case:StaticInitizlization.java
//StaticInitizlization.java
class Bowl{
Bowl(int marker){
System.out.println("Bowl("+marker+")");
}
void f(int marker){
System.out.println("f("+marker+")");
}
}
class Table{
static Bowl b1=new Bowl(1);
Table(){
System.out.println("Table()");
b2.f(1);
}
void f2(int marker){
System.out.println("f2("+marker+")");
}
static Bowl b2=new Bowl(2);
}
class CupBoard{
Bowl b3=new Bowl(3);
static Bowl b4=new Bowl(4);
CupBoard(){
System.out.println("CupBoard()");
b4.f(2);
}
void f3(int marker){
System.out.println("f3("+marker+")");
}
static Bowl b5=new Bowl(5);
}
public class StaticInitialization{
public static void main(String args[]){
System.out.println("Creating new CupBoard() in main");
new CupBoard();
System.out.println("creating new Cupboard()" );
new CupBoard();
}
static Table t2=new Table();
static CupBoard t3=new CupBoard();
}
初始化顺序
1>类型为Dog的一个对象首次创建时,或者Dog类的静态方法数据首次访问时,Java解释器必须找到Dog.class.
2>找到Dog.class后,它的所有的静态初始化模块都会运行.因此静态初始化仅发生一次.
3>创建一个new Dog()时, new语句首先会在堆里分配一足够的空间.
4>这个空间将会被清除为零,因此Dog中的所有的数据成员都得到了缺省值.
5>执行定义初始化.
6>执行构造函数(先静后动).
显式初始化
Java允许我们将其他静态初始化工作划分到类内一个特殊的"静态构造从句"(有叫"静态块")
Java1.1可以用类似的方法初始化非静态数据成员.
<1>隐藏实施过成---访问控制
A primary consideration in objecdt-oriented design is "separating the things that change from the
things that stay the same."
两种人:1>创建类的人.2>用别人的类创造自己类的人.
每个库的用户(client programmer)必须能依赖自己使用的库,并知道一旦新版本的库推出,自己不需要改写代码.
<2>包:库单元
1>用import来引如包或包里的成员.
import java.util.*;
import java.util.Vector;
之所以要这样的引入,是为了提供一种特殊的机制,来实现命名空间的管理.
引入包机制来确定唯一的类.
2>编译单元
每个编译单元必须是以.java结尾的文件名称,在一个编译单元里,可以有一个public的类,这个类的名字必须与文件的名字相同.在一个单元内,只能有一个public的类.
3>编译一个.java文件时,对应于文件中的每一个类,会得到一.class文件,文件名与类的名字相同.一程序是一对.class文件.
4>定义包
一个库是一堆这样的.class文件,它们被定义为一个包,但是并不真真地合并在一个文件中.
package mypackage;//声明一个包
public class MyClass;
现在,如果客户程序员想要用MyClass,就要用import来引入mypackage包,或者是使用MyClass的全名.
import mypackage;
MyClass m=new MyClass();
mypackage.MyClass m=new mypackage.MyClass();
5>CLASSPATH(环境变量)
将某个特定包使用的所有.class文件都放在一个目录下.
CLASSPATH包含一个或多个目录,它们作为一种特殊的根使用,从这里展开对.class的搜索.
-自动编译
-冲突
<3>类成员的访问属性
1>针对类内的每个成员的每个定义,java访问属性public,protected和private都放在它们的前面--无论是数据成员还是方法.
2>-"friendly"(缺省包)
-public:界面访问(accessor/mutator)
-private:不能接触!
<4>类的访问控制
1>一个编译单元(文件)中只能有一个public的类.因此一个编译单元只有一个唯一的公共界面,其余的类都是"frendly"的.public类的名字必须和文件的名字一样.
2>可见,尽管很少见,一个编译单元没有一个public类,所有的类都是"friendly"的,那么文件名可以任意起.
//Lunch.java
//Demonstrates class access specifiers.
//Make a class effectively private
//with private constructor:
class Soup{
private Soup(){}
//(1)Allow creation via static method:
public static Soup makeSoup(){
return new Soup();
}
//(2)Create a static object and
//return a reference upon request.
//(The "Singleton" pattern):
-protected:"某种友好"(同一包中的类和子类能访问)
继承与多态性
<1>继承
class ThisClass extends SuperClass{
//class body
}
1>Java只能做单继承
//Detergent.java
//Inheritance syntax & properties
class Cleaner{
private String s = new String("Cleanser");
public void append(String a){s+=a;}
public void dilute(){ append("dilute()");}
public void scrub(){ append("scrub()");}
public void apply(){ append("apply()");}
public void print(){ append("System.out.print(s);}
public static void main(String args[])
{
Cleanser x= new Cleanser();
x.dilute();
x.apply();
x.scrub();
x.print();
}
}
public class Detegent extends Cleanser{
// Change a method:
public void scrub(){
append("Detergent.scrub()");
super.scrub();
}
// Add methods to the interface
public void foam(){append("foam()");}
// Test the new class
public static void main(String args[])
{
Detergent x = new Detegent();
x.dilute();
x.apply();
x.scrub();
x.foam();
x.print();
System.out.println("Testing base class:"
Cleanser.main(args);
}
}
2>传递构造参数
3>初始化和类的装载
//:beet.java
//the full pocess of initialization.
class Insect{
int i=9;
int j;
Insect(){
prt("i="+i+",j="+j);
j=39;
static int x1=prt("static Insect.x1 initialized");
static int prt(String s){
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect{
int k=prt("Beetle.k initialized");
Beetle(){
prt("k="+k);
prt("j="+j);
}
static int x2=prt("static Beetle.x2 initialized");
4>Upcasting
is taking an object handle and treating it as the handle of its base type.
字类和父类之间的关系是:The new class is a type of the existing class.
Upcasting 是安全的.
//:Wind.java
//Inheritance & upcasting
import java.util.*;
class Instrument{
protected void play(){System.out.println("Instrument playing");
static void tune(Instrument i){
i.play();
}
}
//Wind obuect are instruments
//because then have the same interface:
class Wind extends Instrument{
protected void play(){System.out.println("Wind playing");}
public static void main(String args[]){
Wind flute=new Wind();
Instrument.tune(flute);
}
}
5>Method call binding(绑定)
is connecting a method call to a method body.
早绑定vs.晚绑定(动态/运行时刻)
java中的所有的绑定都是晚绑定,除了final的方法.
6>final
final:This cannot be changed
Final data 只能被赋值一次
// FinalData.java
//The effect of final fields
class Value{
int i=1;
}
public class FinalData{
//Can be compile-time constants
final int i1=9;
static final int I2=99;
//Typical public constant:
public static final int I3=39;
//Cannot be compile-time constants:
final int i4=(int)(Math.random()*20);
static final int i5=(int)(Math.random()*20);
Value v1=new Value();
final Value v2=new Value();
static final Value v3=new Value();
//!final Value v4;
//Arrays:
final int[] a={1,2,3,4,5,6};
public void print(String id){
System.out.print(
7>有两种final方法:
(1,在方法上加一把锁,防止继承者改变它的意义.
(2,编译器把对该方法的调用变成inline调用.
private is final
8>Final classes
Final classes 是不允许被继承的.
Final field in a final class?
Final methods in a final class?
1>抽象类和抽象方法
一个类的作用仅仅是表达接口,而不是具体的实现细节
抽象方法是不完全的,它只是一个申明,没有方法体
包含一个抽象方法的类被称作抽象类
不能制造抽象类的对象
从抽象类继承的类必须override所有的抽象方法,否则它自己成为一个抽象类
可以申明一个抽象类但是里面没有一个抽象方法
//:Music4.java
//Abstract classes and methods
import java.util.*;
abstract class Instrument4{
int i;//storage allocated for each
public abstract void play();
public String what(){
return "Instrument4";
}
public abstract void adjust();
}
class Wind4 extends Instrument4{
public void play(){
System.out.println("Wind4.play()");
}
public String what(){ return "Wind4";}
public void adjust(){}
}
2>Interface //totally abstract class
它的地位和类是一样的,interface没有body,它的成员值在编译是确定的.
This is what alll classes that implement this particular interface will look like.
Public interface InterfaceName extends BaseInterfaces
在interface中所以的方法都是public的,即使你没有申明它是public的.
在interface中所以的数据成员都是public static final的,即使你没有申明.但不能是blank final
Case:Music5.java
interface Instrument5{
// Compile-time constant:
int i=5;//static & final
//Cannot have method definitions:
void play();//Automatically public
String what();
void adjust();
}
class Wind5 implements Instrument5{
public void play(){
System.out.println("Wind5.play()");
}
public String what(){ return "Wind5";}
public void adjust(){ }
class Percussion5 implements Instrument5{
3>实现interface
An class implements an interface to have interface.
实现interface的类,其interface中所以的方法必须被"实现",否则这个类成为一个抽象类.
所以实现interface中的方法必须被申明为public.
interface可以从多个interface得到继承,但是不能继承类.
一个类可以实现多个interface.
4>Inner class(内部类)
1.1版本之后才有内部类,1.1版本中有新的消息机制
In Java 1.1,it is possible to place a class definition within another class definition.
成员函数,成员类
5>Private inner class
Inner classes 可以完全地被封闭起来,不被外界所见到.
Why inner classes?
两个理由要在方法和scope中定义inner class:
1),我们准备实现某种形式的interface,使自己能创建和返回一个句柄.
2),要解决一个复杂的问题,并希望创建一个类,用来辅助自己的程序,同时不愿意把类的细节公开.
其实是一种设计模式
Exception
1>The basic philosophy of Java is that "baddy-formed code will not be run".
总有一些问题是编译时刻预计不到的.
能否很好的处理运行时刻的异常情况是一个程序健康的标志.
中国程序员普遍缺乏异常处理意识.
用户都知道软件没有不出错的,所以要把运行错误报告给用户,而不是试图隐藏.
readFile
{
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
中国人不够细致,考虑主要东西,容易忽视细节问题.
软件一定会出错,消费软件.
2>传统错误处理
c函数中不少都以特殊的返回值标志运行错误.
但是如果你完全检查任何时刻的错误,你的代码就会变成无法阅读的梦魇.
readFile.err
所有的函数都作出返回值处理.
3>Exception机制处理
使用异常机制,读、写和调试代码变得清晰。它把处理错误的代码和正常的代码分开。
readFile.exception
readFile{
try{ //basic logic
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}catch(fileOpenFailed){
doSomething;
}catch(sizeDeterminationFailed){
doSomething;
}catch(momoryAllocationFailed){
doSomething;
}catch(readFailed){
doSomething;
}catch(fileCloseFailed){
doSomething;
}
}
4>Throw an exception
throw new NullPointerException();
throw new NullPointerException("HERE!");//message
异常发生时,你不能解决问题,所以必须仍(throw)出一个异常。
n1:一个异常对象建立起来了。
n2:当前运行的路径别停止,异常对象被弹出(eject).
n3:异常处理机制接管,开始寻找一个适合的地方来继续执行。
5>Catch an exception
Java的异常机制的好处就在与它使2没在一个地方将精力集中在要解决的问题上,而在另一个地方处理来自那部分代码的异常情况。
try{ // Code that may make exception
}catch(Typel id1){
}chach(Type2 id2){
}
6>Match the exception
匹配异常不需要精确匹配。
//:Human.java
//Catching Exception Hierarchies
class Annoyance extends Exception{}
class Sneeze extends Annoyance{}
public class Human{
public static void main(String args[])
{
try{
throw new Sneeze();
}catch(Annoyance a){
System.out.println("Caught Annoyance");
}catch(Sneeze s){
Skystem.out.println("Caught Sneeze");
}
}
}
Exception
1>The basic philosophy of Java is that "baddy-formed code will not be run".
总有一些问题是编译时刻预计不到的.
能否很好的处理运行时刻的异常情况是一个程序健康的标志.
中国程序员普遍缺乏异常处理意识.
用户都知道软件没有不出错的,所以要把运行错误报告给用户,而不是试图隐藏.
readFile
{
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
中国人不够细致,考虑主要东西,容易忽视细节问题.
软件一定会出错,消费软件.
2>传统错误处理
c函数中不少都以特殊的返回值标志运行错误.
但是如果你完全检查任何时刻的错误,你的代码就会变成无法阅读的梦魇.
readFile.err
所有的函数都作出返回值处理.
3>Exception机制处理
使用异常机制,读、写和调试代码变得清晰。它把处理错误的代码和正常的代码分开。
readFile.exception
readFile{
try{ //basic logic
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}catch(fileOpenFailed){
doSomething;
}catch(sizeDeterminationFailed){
doSomething;
}catch(momoryAllocationFailed){
doSomething;
}catch(readFailed){
doSomething;
}catch(fileCloseFailed){
doSomething;
}
}
4>Throw an exception
throw new NullPointerException();
throw new NullPointerException("HERE!");//message
异常发生时,你不能解决问题,所以必须仍(throw)出一个异常。
n1:一个异常对象建立起来了。
n2:当前运行的路径别停止,异常对象被弹出(eject).
n3:异常处理机制接管,开始寻找一个适合的地方来继续执行。
5>Catch an exception
Java的异常机制的好处就在与它使2没在一个地方将精力集中在要解决的问题上,而在另一个地方处理来自那部分代码的异常情况。
try{ // Code that may make exception
}catch(Typel id1){
}chach(Type2 id2){
}
6>Match the exception
匹配异常不需要精确匹配。
//:Human.java
//Catching Exception Hierarchies
class Annoyance extends Exception{}
class Sneeze extends Annoyance{}
public class Human{
public static void main(String args[])
{
try{
throw new Sneeze();
}catch(Annoyance a){
System.out.println("Caught Annoyance");
}catch(Sneeze s){
Skystem.out.println("Caught Sneeze");
}
}
}
1>Catch all kind of exception
一个捕捉任何异常的捕捉器是一个捕捉基本类型的捕捉器。
catch(Exception e){
System.out.println("caught an exception");
}
2>Interface:Throwable
String getMessage();
String toString();
void printStackTrace();//这个异常在那抛出来的
void printStackTrace(PrintStream);
3>Re-throwing
catch(Exception e){
throw e;
}
关于fillInStackTrace();
也可以抛出一与接受到的异常不同的异常
4>Announce for exception
5>Override of exception
当你override一个方法,你只能申明和抛出不比它的父类版本中申明的异常多的异常。
通知客户程序员自己写的方法中可能抛出什么样的异常是一种文明的做法。
void f()throws tooBig.tooSmall,oldStyle
{ // Body off()}
如果你要从你的方法中抛出某种异常,你必须申明。
但是你可以撒谎申明你并不真正抛出的异常。
class A extends Exception{}
class B extends A{}
abstract class I{
void fevent() throws A;
void gent() throws B;
void hent();
}
class C extends Exception{}
class D extends B{}
interface II{
void fevent() throws C;
}
class CC extends I implements II
{
CC() throw A,C{ }
//hent() throws A;
}
5>finally 一定会执行的代码。
6》Run-time exception
if(t==null) throw new NullPointException;
Run-time exception 不需要主动throw
不需要申明
如果一个Run-time exception被系统throw后没有被catch,会导致呈现终止,并printStackTrace()