Java编程学习摘要(3)面向对象
1.类是java中的一种重要的复合数据类型,是组成java程序的基本要素。它封装了一类对象的状态和方法,是这一类对象的原形。一个类的实现包括两个部分:类声明和类体。
[public][abstract|final] class
className [extends superclassName] [implements
interfaceNameList] //类声明
{……}
class
className //类体
{[public | protected | private ][static][final] [transient]
[volatile] type variableName;
[public | protected | private ] [static][final | abstract]
[native] [synchronized]
returnType methodName([paramList]) [throws
exceptionList] //成员方法
{statements} //方法体
}
其中,variableName是成员变量, methodName是成员方法。
static:
静态变量(类变量):相对于实例变量
final: 常量
transient: 暂时变量,用于对象存档
volatile: 共享变量,用于并发线程的共享
成员方法的声明:returnType
methodName([paramList]) [throws exceptionList]
方法体声明的局部变量的作用域在该方法内部。若局部变量与类的成员变量同名,则类的成员变量被隐藏。在方法中,为了区别参数和类的成员变量,我们必须使用this。this-----用在一个方法中引用当前对象,它的值是调用该方法的对象。返回值须与返回类型一致,或者完全相同,或是其子类。当返回类型是接口时,返回值必须实现该接口。
注意:外部参数paramList可以是简单数据类型(数值类型实现值传递不改变数据的值),也可以是复合数据类型(引用类型实现数据在内存中的地址改变数据的值)
方法重载:指多个方法享有相同的名字,但是这些方法的参数必须不同,或者是参数的个数不同,或者是参数类型不同。返回类型不能用来区分重载的方法。
下例说明简单数据类型与引用数据的区别:
import java.io.*;
public class PassTest{
float ptValue;
public static void main(String args[]) {
int val;
PassTest pt=new PassTest();
val=11;
System.out.println("Original Int Value is:"+val);
pt.changeInt(val);
//值参数
System.out.println("Int Value after Change is:" +val);
pt.ptValue=101f;
System.out.println("Original ptValue is:"+pt.ptValue);
pt.changeObjValue(pt); //引用类型的参数
System.out.println("ptValue after Change is:"+pt.ptValue);
}
public void changeInt(int value){
value=55; //在方法内部对值参数进行了修改}
public void changeObjValue(PassTest ref){
ref.ptValue=99f;//在方法内部对引用参数进行了修改}
}
方法重载实例:
import java.io.*;
class MethodOverloading{
void receive(int i) {
System.out.println("Receive one int data");
System.out.println("i="+i);
}
void receive(int x, int y) {
System.out.println("Receive two int datas");
System.out.println("x="+x+" y="+y);
}
}
public class MethodOverloadingTest{
public static void main(String args[]) {
MethodOverloading mo=new MethodOverloading();
mo.receive(1);
mo.receive(2,3);
}
}
构造方法
◇ 构造方法是一个特殊的方法。Java
中的每个类都有构造方法,用来初始化该类的一个对象。
◇ 构造方法具有和类名相同的名称,而且不返回任何数据类型。
◇ 重载经常用于构造方法。
◇ 构造方法只能由new运算符调用
class Point{
int x,y;Point(){
x=0; y=0;
} Point(int x, int y){
this.x=x;
this.y=y;
}
}
2.对象的生命周期:生成->使用->消除
对象的生成:type
objectName=new type([paramlist]);
对象的使用:objectName.variable、objectName.methodName([paramlist]);
对象的消除:System.gc( );
(自动回收释放)
声明只分配引用空间,它存储数据类型信息和当前对象所在堆的地址而不改变对象的实际内存地址(安全)
实例化运算符new为对象分配内存空间,它调用对象的构造方法,返回引用,执行构造方法,进行初始化(根据参数不同调用相应的构造方法);一个类的不同对象分别占据不同的内存空间。
对象消除时,当系统内存用尽或调用System.gc(
)要求垃圾回收时,垃圾回收线程与系统同步运行。
3.Java语言中有三个典型的面向对象的特性:封装性、继承性和多态性
【封装性】
Java中类的限定词的作用范围比较:
类限定词
同一个类
同一个包
不同包的子类
不同包非子类
private
私有类
*
default
缺省类
*
*
protected
受保护类
*
*
*
public
公有类
*
*
*
*
注意:(1)如果一个类的构造方法声明为private,则其它类不能生成该类的一个实例。
(2)缺省类(default)不加任何访问权限限定,可以被该类本身和同一个包中的类所访问。
(3)protected的成员,可被这个类本身、子类(包括同一包和不同包中的子类)和同一包中的所有其他类访问。
(4)public的成员,可以被所有(包)的类访问
【继承性】 通过继承实现代码复用
Java中所有的类都是通过直接或间接地继承java.lang.Object类得到。继承而得到的类称为子类,被继承的类称为父类。子类不能继承父类中访问权限为private的成员变量和方法。子类可以重写父类的方法,命名与父类同名的成员变量。但Java不支持多重继承,即一个类从多个超类派生的能力。◇创建子类:class SubClass extends SuperClass {…}
成员变量的隐藏和方法的重写,可以把父类的状态和行为改变为自身的状态和行为:
class SuperClass{
int x; …
void setX( ){ x=0; } …
}
class SubClass extends SuperClass{
int x; //隐藏了父类的变量x
…
void setX( ) { //重写了父类的方法
setX()
x=5; } ….
}
注意:子类中重写的方法和父类中被重写的方法要具有相同的名字,相同的参数表和相同的返回类型,只是函数体不同。
【多态性】
◇对父类成员访问:super
Super 的使用有三种情况:
1)访问父类被隐藏的成员变量,如:
super.variable;
2)调用父类中被重写的方法,如:
super.Method([paramlist]);
3)调用父类的构造函数,如:
super([paramlist]);
重写方法的调用原则:java运行时系统根据调用该方法的实例,来决定调用哪个方法。对子类的一个实例,如果子类重写了父类的方法,则运行时系统调用子类的方法;如果子类继承了父类的方法(未重写),则运行时系统调用父类的方法。如下例:
import java.io.*;
class A{
void callme( ) {
System.out.println("Inside A's callme()method");
}
}
class B extends A{
void callme( ) {
System.out.println("Inside B's callme() Method");
}
}
public class Dispatch{
public static void main(String args[]) {
A a=new B(); //A父类建立了B子类的对象实例
a.callme( ); //A父类对象a调用了B子类对象的方法
}
}
运行结果:c:\> java Dispatch
Inside B's callme() method
方法重写时应遵循的原则:
1)改写后的方法不能比被重写的方法有更严格的访问权限(可以相同)。
2)改写后的方法不能比重写的方法产生更多的异常。
4.其他:final修饰作用,static修饰类变量,类java.lang.Object的常用方法
final的修饰作用:
1) final 修饰类成员变量:
final修饰变量,则成为常量,例如
final type variableName;
修饰成员变量时定义时同时给出初始值,而修饰局部变量时不做要求。
2)final 修饰类成员方法:
final修饰方法,则该方法不能被子类重写 final returnType
methodName(paramList){
…
}
3)final 修饰类本身:
final修饰类,则类不能被继承 final class
finalClassName{
…
}
static修饰类变量:
类变量仅在生成第一个对象时分配内存,所有实例对象共享同一个类变量,每个实例对象对类变量的改变都会影响到其它的实例对象。类变量可通过类名直接访问,无需先生成一个实例对象,也可以通过实例对象访问类变量。但类方法不能访问实例变量,只能访问类变量。类方法可以由类名直接调用,也可由实例对象进行调用。类方法中不能使用this或super关键字。
下面是一个关于实例成员和类成员的例子:
class Member {
static int
classVar; //类变量 int
instanceVar;
//实例变量 static void
setClassVar(int i) {
classVar=i;
// instanceVar=i; //
类方法不能访问实例变量,只能访问类变量
}
static int
getClassVar() //类方法 {
return classVar; }
void setInstanceVar(int i)
{ classVar=i; //实例方法不但可以访问类变量,也可以实例变量
instanceVar=i; }
int getInstanceVar( )
{ return instanceVar; }
}
public class MemberTest{
public static void main(String args[])
{
Member m1=new member();
Member m2=new member();
m1.setClassVar(1);
m2.setClassVar(2);
System.out.println("m1.classVar="+m1.getClassVar()+"
m2.ClassVar="+m2.getClassVar());
m1.setInstanceVar(11);
m2.setInstanceVar(22);
System.out.println("m1.InstanceVar="+m1.getInstanceVar
()+" m2.InstanceVar="+m2.getInstanceVar());
}
}
类java.lang.Object的常用方法:
java.lang.Object处于java开发环境的类层次的根部,其它所有的类都是直接或间接地继承了此类。该类定义了一些最基本的状态和行为。
equals() :比较两个对象(引用)是否相同。
getClass():返回对象运行时所对应的类的表示,从而可得到相应的信息。
toString():用来返回对象的字符串表示。
finalize():用于在垃圾收集前清除对象。
notify(),notifyAll(),wait():用于多线程处理中的同步。
5.抽象类和接口:
抽象类:abstract class abstractClass{
…}
抽象方法:abstract returnType
abstractMethod([paramlist])
接口:[public] interface
interfaceName[extends
listOfSuperInterface] { … }
【注意】抽象类必须被继承,抽象方法必须被重写。抽象方法只需声明,无需实现;抽象类不能被实例化,抽象类不一定要包含抽象方法。若类中包含了抽象方法,则该类必须被定义为抽象类。
接口是抽象类的一种,只包含常量和方法的定义,而没有变量和方法的实现,且其方法都是抽象方法。
extends 一个接口可有多个父接口,用逗号隔开,而一个类只能有一个父类。
(1)接口的作用:
◇ 通过接口实现不相关类的相同行为,而无需考虑这些类之间的关系。
◇ 通过接口指明多个类需要实现的方法。
◇ 通过接口了解对象的交互界面,而无需了解对象所对应的类。
(2)接口体:常量体 + 方法体
常量体定义格式(该常量被实现该接口多个类共享; 有public ,final,static的属性):
type NAME=value;
方法体定义格式(具有public和abstract属性):
returnType methodName([paramlist]);
(3)接口的实现:implements子句来表示一个类使用某个接口,在类体中可以使用接口中定义的常量,而且必须实现接口中定义的所有方法。一个类可以实现多个接口,在implements子句中用逗号分开。
(4)接口类型的使用:作为一种引用类型。任何实现该接口的类的实例都可以存储在该接口类型的变量中,通过这些变量可以访问类所实现的接口中的方法。
6.内部类:Inner
Class
定义:在一个类的内部嵌套定义的类,可以是其它类的成员,也可以在一个语句块的内部定义,还可以在表达式内部匿名定义。
性质:a.可以使用包含它的类的静态和实例成员变量,也可以使用它所在方法的局部变量。
b.
可以定义为abstract。可以声明private或protected。若被声明为static,就变成了顶层类,不能再使用局部变量。c.若要在内部类中声明static成员,必须把整个内部类申明为static。
举例来说明内部类如何使用,其中定义了两个内部类:MouseMotionHandler和MouseEventHandler,分别用来处理鼠标移动事件和鼠标点按事件。
import java.awt.*;
import java.awt.event.*;
public class TwoListenInner {
private Frame
f; //类成员变量
private TextField tf;
public static void main(String args[])
{ //主函数入口
TwoListenInner that=new TwoListenInner();
that.go(); }
public void go()
{ //类成员方法go()
f=new Frame("Two listeners example");
f.add("North",new Label("Click and drag the mouse"));
tf=new TextField(30);
f.add("South",tf);
f.addMouseMotionListener(new
MouseMotionHandler() );
//调用内部类 f.addMouseListener(new
MouseEventHandler()
); //调用内部类
f.setSize(300,300);
f.setVisible(true);
}
public class MouseMotionHandler extends
MouseMotionAdapter { //处理鼠标拖曳事件
public void mouseDragged(MouseEvent e){
String s="Mouse dragging:X="+e.getX()+"Y="+e.getY();
tf.setText(s);
}
}
public class MouseEventHandler extends
MouseAdapter { //处理鼠标移动事件
public void mouseEntered(MouseEvent e){
String s="The mouse entered";
tf.setText(s);
}
public void mouseExited(MouseEvent e){
String s="The mouse left the building";
tf.setText(s);
}
}
}
匿名类:一种特殊的内部类,它是在一个表达式内部包含一个完整的类定义。如上例中在go()方法中修改:
f.addMouseMotionListener(new
MouseMotionHandler() {
public void
mouseDragged(MouseEvent e){
String s="Mouse dragging:X="+e.getX()+"Y
="+e.getY();
tf.setText(s);
}}
);