1 什么是过程语言?
面向过程编写的程序语言成为过程语言 其源文件的特点是更接近人的自然语言。使用过程语言 人们只需要按照自己的意图来编写各种函数 编写语言的程序和语法更接近人们的自然语言 习惯上称过程语言为高级语言。高级语言不能被计算机直接识别 其源文件必须转换成机器指令 然后计算机去执行相关的机器指令
将高级语言转换成机器识别的机器指令通常有两种方式:
第一种:编译方式 针对当前的机器处理芯片 将源文件全部翻译成机器指令 成为目标程序 再将目标程序交给计算机执行
第二种:解释方式 这种方式不产生 目标程序 而是根据目前的机器处理芯片 便解释边执行 解释一句执行一句
Java执行方式不在上述之列 其高明之处在于它不针对当前的cpu芯片进行编译 java提供的编译器把源文件编译成字节码的中间代码,字节码与机器代码相似 但是可以在提供了java虚拟机的任何系统上运行。Java本质上是解释执行的程序 当字节码加载到内存之后再有java的解释器对字节码按照解释方式进行边解释边执行。
2 面向对象编程
面向对象编程是一种高级的思维模式具有封装性 继承和多态的性质
封装性 就是将数据和对数据的操作封转在一起 通过抽象 即从具体的实例中抽取共同的性质形成的一般的概念
继承体现了一种先进的模式 子类可以继承父类的所有功能和属性 同时又可以增添自己的数据和对数据的操作
多态有两种意义的多态一种是操作名称的多态即有多个操作具有相同的名称但这些操作必须接到不同的数据类型
1 类是java的基本要素 类封装了一些方法和对象的状态 类是定义对象的模板
类的实现包含两个部分:类声明和类体
Class People 类声明
{int year;} 类体
成员变量和局部变量 :成员变量在整个类中有效 局部变量只在类方法中有效 成员变量又分为实例变量和静态变量(类变量)静态变量前面加上static
成员变量的名字和局部变量相同的话 则成员变量将被隐藏 这个变量在方法中暂时失效 如果想在方法中使用这个成员变量 则必须使用this关键字
class People
{int x;
void float fun(int x)
{
this.x=x
}
}
2 方法
方法等同与c语言中的函数
方法重载就是一个类中有多个方法具有相同的名字 但是参数类型或者个数不同
3 构造方法 是一种特殊的方法 它的名称与类的名字完全相同 而且没有类型 构造方法也可以重载
class tixing //定义类
{float 上底,下底,高; //定义属性也就是成员变量
tixing() //调用构造函数
{上底=20;下底=30;高=50;//构造函数赋值
}
tixing(float x,float y,float z) //定义构造函数并定义其内部变量
{上底=x;
下底=y;
高=z;
}
}
4 类方法和实例方法
加上static定义的方法称为类方法 不加的为实例方法
5、注意事项
对成员变量的操作只能放在方法中 方法可以对成员变量和方天体重自己定义的局部变量进行操作 在定义类中的成员变量可以同时赋值即 int x=18;合理 但是 int x;x=18;就是错的了 因为类体的内容是由变量的定义和方法的定义两部分组成
实例方法即可以对类变量进行操作也可以对实例变量进行操作 而类方法只能对类变量进行操作 即static方法只能操作static变量
一个类的方法可以互相调用 实例方法可以调用该类中的其他方法 类中的类方法只能调用该类中的类方法
1 当使用类创建一个对象时候就说是给出了这个类一个实例
创建对象包括对象声明和对象分配内存加入People是类名 则有 People zhangxin;这就定义了一个实例对象 要分配空间zhangxin=new People();这就分配了内存空间
声明对象之后 对象里没有任何数据 这时候对象就是一个空对象 不能使用 因为还没有得到任何实体 必须再进行对象分配内存的步骤 即为对象分配实体
People zhangxin=new People();会做两件事情 第一为People类中的各个成员变量分配内存空间 赋予初值 然后执行构造方法中的语句 第二 给出一个信息确保这些变量属于zhangxin的 即这些内存单元将由zhangxin来操作管理 为了做到这一点 new运算符在为变量分配空间后将返回一个引用给对象变量zhangxin 也就是返回一个代表这些成员变量内存首地址的重要信息给zhangxin 可以认为这个引用就是zhangxin在内存中的名字 而且这个名字确保java系统将分配给各个成员变量的内存单元将由zhangxin操作管理 称各个变量分配的内存单元是属于对象zhangxin的实体 也就是这些变量是属于zhangxin的
所谓分配内存就是为其分配变量 并获得一个引用 这些变量是属于zhangxin的
可以同时创建多个对象并分配相应的内存空间(引用等同于指针)
2 使用对象
对象操作自己的变量和方法 用点运算符 当对象调用类中的一个方法时 方法中的局部变量被分配了空间 方法执行完毕 局部变量即刻释放内存
例子 xiyourenwu
class Xiyourenwu
{float height,weight;
String head,ear,foot,mouth;
void speak(String s)
{head="";
System.out.println(s);
}
}
class Example41
{ public static void main(String args[])
{Xiyourenwu sunwukong=new Xiyourenwu();
Xiyourenwu zhubajie=new Xiyourenwu();
zhubajie.height=1.8f;
zhubajie.head="大头";
zhubajie.ear="一双大耳朵";
sunwukong.height=1.62f;
sunwukong.weight=1000f;
sunwukong.head="秀发飘飘";
System.out.println("zhubajie的身高"+zhubajie.height);
System.out.println("zhubajie的头"+zhubajie.head);
System.out.println("sunwukong得重量"+sunwukong.weight);
System.out.println("sunwukong的头"+sunwukong.head);
zhubajie.speak("俺老猪我想娶媳妇");
System.out.println("zhubajie现在的头"+zhubajie.head);
sunwukong.speak("老孙我重1000斤,我想骗猪八戒背我");
System.out.println("sunwukong现在的头"+sunwukong.head);
}
}
类中的方法可以操作成员变量 当对象调用该方法的时候 方法中出现的成员变量就是对象中的成员变量 当对象zhubajie调用了speak之后 就将自己的头改写成了歪着头了
实例 梯形
class 梯形
{ float 上底,下底,高,面积;
梯形(float x,float y,float h)
{上底=x;
下底=y;
高=h;
}
float 计算面积()
{面积=(上底+下底)*高/2.0f;
return 面积;
}
void 修改高(float height)
{高=height;
}
float 获取高()
{return 高;
}
}
public class Example42
{public static void main(String args[])
{梯形 laderOne = new 梯形(12.0f,3.5f,50);
梯形 laderTwo = new 梯形(2.67f,3.0f,10);
System.out.println("laderOne的高:"+laderOne.获取高());
System.out.println("laderTwo的高:"+laderTwo.获取高());
System.out.println("laderOne的面积:"+laderOne.计算面积());
System.out.println("laderTwo的面积:"+laderTwo.计算面积());
laderOne.修改高(10);
float h = laderOne.获取高();
laderTwo.修改高(h*2);
System.out.println("laderOne现在的高:"+laderOne.获取高());
System.out.println("laderTwo现在的高:"+laderTwo.获取高());
System.out.println("laderOne现在的面积:"+laderOne.计算面积());
System.out.println("laderTwo现在的面积:"+laderTwo.计算面积());
}
}
注意事项 一定在英文字符下编写程序以及而且在命名的时候不能有空格
3 对象的引用和实体
当类创建一个对象时 类中的成员变量被分配内存空间 这些内存空间成为该对象的实体 而对象中存放着引用 以确保实体由该对象操作使用
如果程序中使用了空对象 则会发生异常 也就是NullPointerException异常
4 参数传值
如果方法被调用时 方法有参数 则参数必须实例化 即参数必须有具体的值 在java中 方法的所有参数都传值的
基本数据类型传值 向参数传递的值的级别不可以高于该参数的级别
引用类型参数的传值
Java的引用型数据包括对象 数组和接口 当参数是引用类型时 传值传递的是变量的引用而不是变量的实体 如果改变了参数变量的引用的实体 就会导致原变量的实体发生同样的变化 因为同类型的引用型变量如果具有相同的引用 就会指向相同的实体 但是 改变参数的引用不会影响向其传值的变量的引用
实例如下:class 圆
{double 半径;
圆(double r)
{半径=r;
}
double 计算面积()
{return 3.14*半径*半径;
}
void 修改半径(double 新半径)
{半径=新半径;
}
double 获取半径()
{return 半径;
}
}
class 圆锥
{圆 底圆;
double 高;
圆锥 (圆 circle,double h)
{this.底圆=circle;
this.高=h;
}
double 计算体积()
{double volume;
volume=底圆.计算面积()*高/3.0;
return volume;
}
void 修改底圆半径(double r)
{底圆.修改半径(r);
}
double 获取底圆半径()
{return 底圆.获取半径();
}
}
class Example44
{ public static void main(String args[])
{圆 circle=new 圆(10);
圆锥 circular = new 圆锥(circle,20);
System.out.println("圆锥底圆半径:"+circular.获取底圆半径());
System.out.println("圆锥的体积:"+circular.计算体积());
circular.修改底圆半径(100);
System.out.println("圆锥底圆半径:"+circular.获取底圆半径());
System.out.println("圆锥的体积:"+circular.计算体积());
}
}
实例变量与类变量的区别 一个类通过new运算符可以创建不同的多个对象 这些对象非配不同的内存空间 不同的对象的实例变量将分配不同的内存空间 但是如果类中成员变量为类变量 则所有对象的这个类变量都分配给同一个内存 改变其中一个对象的这个类变量会影响到其他对象的这个类变量
当java程序执行的时候 类的字节码被加载到内存 如果该类没有创建对象 则实例变量不会分配内存 但是类中的类变量被加载到内存时 就分配了相应的内存空间 如果该类创建对象 那么不同类的实例变量不相同 也就是分配不同的内存空间 但是类变量不再分配内存 也就是所有对象共享一个类变量 也就是说所有对象共享一处内存空间 类变量的 内存空间直到程序退出才会释放所占的内存 类变量可以通过类名访问 也可以通过对象操作类变量
实例方法和类方法的区别
用static修饰的方法就是类方法
一个类创建一个对象的时候 这个对象就可以调用该类的方法
当类的字节码被加载到内存时 类的实例变量不会分配入口地址 创建对象后 类的实例方法才会分配入口地址 从而实例方法可以被类创建的任何对象调用执行 当创建第一个对象的时候 类中的实例方法就分配了入口地址 以后再创建的时候就不需要再次分配入口地址 也就是说方法的入口地址被所有对象共享 当所有对象都不存在时候 方法的入口地址才被取消 实例方法必须通过对象来调用
对于类中的类方法 程序加载的时候就分配了入口地址 从而得出类方法不仅可以用类创建的对象调用 也可以使类名调用 但不管是类方法还是实例方法 方法中的局部变量只有在方法被调用执行的时候才被分配内存
this 关键字表示某个对象 this可以出现在实例方法中也可以出现在构造方法中 但不可以出现在类方法中
this关键字出现在类的构造方法中表示该构造方法创建的对象 实例方法必须通过对象来调用 当this关键字出现在类的实例方法中的时候 代表正在调用该方法的当前对象
实例成员对象在实例方法中出现 则可以表示为this点成员变量
Class A
{ int x;
Static int y;
Void f() this代表方法f的当前对象
{this.x=100; this.x就表示当前对象的变量x
A.y=200;
}
}
Package 包名 来定义一个包 如果使用了package tom.jiafei则目录必须包含/tom/jiafei
例子package tom.jiafei;
public class PrimNumber
{public void getPrimnumber(int n)
{int num=0,i,j;
for(i=1;i<=n;i++)
{for(j=2;j<=i/2;j++)
{if(i%j==0)
break;}
if(j>i/2)
System.out.println(" "+i);
}
}
public static void main(String args[])
{PrimNumber p=new PrimNumber();
p.getPrimnumber(20);
}
}
此次保存目录为C:/shiyongjiaocheng2/lesson4/tom/jiafei 源文件
注意:编译的时候必须和平常一样 但是 执行的时候 一定要回到tom.jiafei的上层文件夹中C:/shiyongjiaocheng2/lesson4>java tom.jiafei.PrimNumber
Import语句
使用import语句可以引用包中的类 在一个java源程序里面可以有多个import语句 他们必须写在package语句和源文件中类的定义之间 如果要引用包中所有的类 则可以用* 如
Import java.util.*来表示引用包中的所有类
比如 例子
import java.applet.Applet;
import java.awt.*;
public class Example45 extends Applet
{Button redbutton;
public void init()
{redbutton=new Button("我是一个红色的按钮");
redbutton.setBackground(Color.red);
redbutton.setForeground(Color.white);
add(redbutton);
}
}
系统自动调用java.lang中的类 因此不必要在显示使用import类来引入该包中的类 使用import引用整个包的类 可能会增加编译时间 但绝对不会影响程序的性能 因为当程序执行的时候 只是将真正使用的类的字节码文件加载到内存
为了使用tom.jiafei这个包中的类 必须在classpath中指明位置
set classpath=C:/Program Files/Java/jre6/lib/rt.jar;.; C:/shiyongjiaocheng2/lesson4
将类打包
package tom.jiafei;
package tom.jiafei;
public class Trangle
{double sideA,sideB,sideC;
boolean boo;
public Trangle(double a,double b,double c)
{sideA=a;
sideB=b;
sideC=c;
if(a+b>c&&b+c>a&&c+a>b)
{System.out.println("我是一个三角形");
boo=true;
}
else
{System.out.println("我不是一个三角形");
boo=false;
}
}
public void 计算面积()
{if(boo)
{ double p =(sideA+sideB+sideC)/2.0;
double area=Math.sqrt(p*(p-sideA)*(p-sideB)*(p-sideC));
System.out.println("三角形的面积"+area);
}
else
{System.out.println("我不是一个三角形,不能计算面积");}
}
public void 修改三边(double a,double b,double c)
{
sideA=a;
sideB=b;
sideC=c;
if(a+b>c&&b+c>a&&c+a>b)
{
boo=true;
}
else
{
boo=false;
}
}
}
将classpath设置一下 之后可以运行下面的程序
import tom.jiafei.Trangle;
class Example47
{public static void main(String args[])
{Trangle trangle=new Trangle(12,3,1);
trangle.计算面积();
trangle.修改三边(3,4,5);
trangle.计算面积();
}
}
将类打包即可
所谓访问权限就是看对象是否可以通过.运算符来操作自己的变量
Private 私有变量 当在另外一个类中创建一个对象的时候 该对象不能访问自己的私有变量和私有方法 对于私有成员变量方法 只有在本类中创建对象时候 这个对象才能访问自己的私有变量和私有方法
共有变量和共有方法 用public修饰的方法和变量称之为共有变量和共有的方法
友好变量和友好方法 不用public protect 以及private修饰的变量和方法称之为友好方法和友好变量
如果在另外一个类中 用本类创建一个对象后 如果这两个类在同一个包中 那么另外的类也可以通过该对象访问自己的友好变量和友好方法 在任何一个和此类在同一个包的类都可以采用该类的类名访问该类的友好变量和友好方法
注意 如果引用了其他包中的类 则不能通过对象和类名来操作该类中的友好变量和友好方法
受保护的变量和方法 与友好变量和友好方法只是在继承方面上稍有区别
访问权限顺序为 public protected 友好变量 private
子类 class子类名 extends 父类名
继承就是子类可以自由地使用父类中的方法和变量 如果在同一个包中 则子类继承父类中除了private的变量和方法 访问权限不变
如例子
class Father
{private int money;
float weight,height;
String head;
void speak(String s)
{System.out.println(s);
}
}
class Son extends Father
{String hand,foot;
}
public class Example48
{ public static void main(String args[])
{
Son boy=new Son();
boy.weight=1.80f;
boy.height=120f;
boy.head="一个大头";
boy.hand="两只手";
boy.foot="两只脚";
boy.speak("我是儿子");
System.out.println(boy.weight+boy.height+boy.head+boy.hand+boy.foot);
}
}
子类如果和父类不再一个包中 则子类可以继承父类的protected 和public变量 不能继承友好变量和友好方法
关于protected类的说明
如果a类继承了b类的protected变量 那么c类只要和b类在同一个包中 那么目标对象就可以使用继承的protected变量和方法
成员变量的隐藏和重写
子类可以继承父类的方法和变量 在子类中定义一个和继承的变量重名的变量 就会将父类方法隐藏 如果定义一个和父类重名的方法 则就是重写方法 重写的方法既可以操作继承的成员变量 也可以操作子类定义和声明的成员变量 如果相使用隐藏的成员变量 必须使用super关键字
重写父类方法时不能降低方法的访问权限 可以高于 但不能低于
Final关键字
final可以修饰方法 变量以及成员中的参数 final类不能被继承 final class a 则a不能有子类
java提供的string类不可以轻易修改 因此被定义为final类 如果一个方法是final类 则此方法不能被修改 如果一个变量是final类的 则此变量在定义时候必须赋值 参数是final的 则不能被修改
B类是 A类的直接子类或者间接子类当用子类 B创建一个对象的时候 并将这个引用放到 A类的对象中时 那么就称A类的对象a是子类对象b的上转型对象
形式如 A a;a=new B (); 或者 A a; B b =new B ();a=b;
对象的上转型对象的实体是子类负责创建的 但上转型对象会失去院子类对象的一些属性和功能
上转型对象不能操作子类新增的成员变量和方法 可以操作父类隐藏的成员变量和方法 也就可以使用子类继承或者重写的成员变量和方法
上转型对象操作子类继承或者重写的方法时 就是通知对应的子类对象调用这些方法 因此 如果子类重写了父类的某个方法后 对象的上转型对象调用这个方法的时候 一定是调用了这个重写了的方法 可以将对象的上转型对象再强制转换到一个子类对象 这时 该子类对象又具备了子类的所有属性和功能
class 类人猿
{private int n=100;
void crySpeak(String s)
{System.out.println(s);
}
}
class People extends 类人猿
{void computer(int a,int b)
{int c=a*b;
System.out.println(c);
}
void crySpeak(String s)
{
System.out.println("**"+s+"**");
}
}
class Example49
{ public static void main(String arg[])
{类人猿 monkey =new People();
monkey.crySpeak("I love this game");
People people=(People)monkey;
people.computer(10,10);
}
}
当一个类有很多子类的时候 这些子类都重写了某个方法 那么当把这些子类创建的对象的引用放到一个父类的对象中时就得到该对象的一个上转型对象 那么这个上转的对象再调用这个方法的时候就具有了多种形态,多态性就是指父类的某个方法被其子类重写的时候 可以产生自己的行为功能。
class 动物
{void cry()
{}
}
class 狗 extends 动物
{void cry()
{System.out.println("汪汪。。。。。");
}
}
class 猫 extends 动物
{void cry()
{System.out.println("喵喵。。。。。");
}
}
class Example410
{public static void main(String args[])
{动物 dongwu;
dongwu=new 狗();
dongwu.cry();
dongwu=new 猫();
dongwu.cry();
}
}
abstract类中可以有abstract方法 对于abstract方法只能声明不能实现 而且不允许final修饰abstract方法 abstract类也可以没有abstract方法
abstract类不能用new运算符创建对象 需要产生子类 由子类创建对象 而且子类必须具体实现父类的abstract方法 这就是为什么不能用final修饰abstract方法的原因
一个abstract抽象类只关心它的子类是否具有某种功能 并不关心功能的具体行为 功能的具体行为由子类负责实现 抽象类中的抽象方法可以强制子类必须给出这些方法的具体实现
abstract class 图形
{ public abstract double 求面积();
}
class 梯形 extends 图形
{double a,b,h;
梯形(double a,double b,double h)
{this.a=a;
this.b=b;
this.h=h;
}
public double 求面积()
{return((1/2.0)*(a+b)*h);
}
}
class 圆形 extends 图形
{double r;
圆形(double r)
{this.r=r;
}
public double 求面积()
{return(3.14*r*r);
}
}
class 堆
{图形 底;
double 高;
堆(图形 底,double 高)
{ this.底=底;
this.高=高;
}
void 换底(图形 底)
{this.底=底;
}
public double 求体积()
{return (底.求面积()*高)/3.0;
}
}
public class Example412
{public static void main(String args[])
{堆 zui;
图形 tuxing;
tuxing=new 梯形(2.0,7.0,10.7);
System.out.println("梯形的面积"+tuxing.求面积());
zui=new 堆(tuxing,30);
System.out.println("梯形底的堆的体积"+zui.求体积());
tuxing=new 圆形(10);
System.out.println("半径是10的圆的面积"+tuxing.求面积());
zui.换底(tuxing);
System.out.println("圆形底的堆的体积"+zui.求体积());
}
}
子类不继承父类的构造方法 子类想用父类的构造方法必须在子类的构造方法中使用 并且必须用关键字super来表示 而且super必须是子类构造方法中的头一条语句
class Student
{int number;
String name;
Student()
{
}
Student(int number,String name)
{this.number=number;
this.name=name;
System.out.println("I am"+name+"my number is "+number);
}
}
class Univer_Student extends Student
{boolean 婚否;
Univer_Student(int number,String name,boolean b)
{super(number,name);
婚否=b;
System.out.println("婚否"+婚否);
}
}
public class Example413
{public static void main(String args[])
{Univer_Student zhang=new Univer_Student(9901,"何晓琳",false);
}
}
如果在子类的构造方法中没有用使用关键字super调用父类的某个构造方法 那么默认有super() 即调用父类不带参数的构造方法 如果子类定义了一个或者多个构造方法 那么java不提供默认的构造方法
使用super关键字可以使用被子类隐藏的父类的成员变量和成员方法
class Sum
{int n;
float f()
{float sum=0;
for(int i=1;i<=n;i++)
sum=sum+i;
return sum;
}
}
class Average extends Sum
{int n;
float f()
{float c;
super.n=n;
c=super.f();
return c/n;
}
float g()
{float c;
c=super.f();
return c/2;
}
}
public class Example414
{public static void main(String args[])
{Average aver=new Average();
aver.n=100;
float result_1=aver.f();
float result_2=aver.f();
System.out.print("result_1="+result_1);
System.out.print("result_2="+result_2);
}
}
Java不支持多继承 但是接口的出现可以解决这个问题 一个类可以实现多个接口
接口声明 interface 接口的名字
接口体中包括定义常量和定义方法 接口的方法只进行声明 不进行实现
接口的使用 一个类可以通过implements声明自己使用一个或者多个接口 如果使用多个接口 用逗号分开即可
如果一个类使用了一个接口 那么这个类必须实现接口的所有方法 即为这些方法提供方法体 在类中实现接口的方法时 方法的名字 返回类型 参数个数以及类型必须和接口中的方法一致 接口中的方法默认为public static类型 所以实现的接口方法必须给出方法体
如果接口中的方法的返回类型不是void型 那么在类中实现该接口方法适合 方法体至少有一个return语句 如果是void型的 类体除了两个大括号外 也可以没有任何语句
interface Computable
{int max=100;
int f(int x);
}
class China implements Computable
{int number;
public int f(int x)
{int sum =0;
for(int i=1;i<=x;i++)
{sum=sum+i;
}
return sum;
}
}
class Japan implements Computable
{int number;
public int f(int x)
{return 44+x;
}
}
public class Example415
{public static void main(String args[])
{China zhang=new China();
Japan hanlu=new Japan();
zhang.number=991819+Computable.max;
hanlu.number=941448+Computable.max;
System.out.println("number:"+zhang.number+"求和"+zhang.f(100));
System.out.println("number:"+hanlu.number+"求和"+hanlu.f(100));
}
}
类实现的接口方法以及常量可以被类的对象调用 而且常量也可以用类名或者接口名直接调用
接口声明的时候 如果接口前加上public 则这个接口可以被任何一个类使用 如果没public 则称之为友好接口 只能被在同一个包中的类使用
如果父类使用了一个接口 那么子类自然使用了这个接口 不用在用implements声明使用这个接口
接口也可以被继承 即可以通过关键字extends声明一个接口是另一个接口的子接口 由于接口中的方法和变量都是public型的 子接口将继承父接口中的所有变量和方法
如果一个类声明实现了一个接口 但没有实现接口中所有的方法 那么这个类必须是abstract类
接口只关系功能 并不关心功能的具体实现
interface 收费
{public void 收取费用();
}
interface 调节温度
{public void controlTemperature();
}
class 公共汽车 implements 收费
{ public void 收取费用()
{System.out.println("公共汽车:一元每张,不计公里数");
}
}
class 出租车 implements 收费,调节温度
{ public void 收取费用()
{System.out.println("出租车:1.60元每公里,起价3元");
}
public void controlTemperature()
{System.out.println("安装了hair空调");
}
}
class 电影院 implements 收费,调节温度
{ public void 收取费用()
{System.out.println("电影院门票十元每张");
}
public void controlTemperature()
{System.out.println("安装了中央空调");
}
}
public class Example416
{ public static void main(String srgs[])
{公共汽车 七路=new 公共汽车();
出租车 天宇=new 出租车();
电影院 红星=new 电影院();
七路.收取费用();
天宇.收取费用();
红星.收取费用();
天宇.controlTemperature();
红星.controlTemperature();
}
}
接口回调是指可以把实现某一个接口的类创建的对象的引用赋给该接口声明的接口变量中
那么该接口就可以调用被类实现的接口中的方法 实际上接口变量调用被类实现的接口中的方法时就是通知相应的对象调用接口的方法
接口变量实现被类调用被类实现的方法 简单一句 接口变量就是对象的引用 也就等于是对象 只不过这个对象是实现这个接口的类创建的对象
interface ShowMessage
{void 显示商标(String s);
}
class TV implements ShowMessage
{public void 显示商标(String s)
{System.out.println(s);
}
}
class PC implements ShowMessage
{public void 显示商标(String s)
{
System.out.println(s);
}
}
public class Example417
{public static void main(String args[])
{ShowMessage sm;
sm=new TV();//对象的引用
sm.显示商标("长城电视机");//等同于new TV().显示商标("长城电视机")
sm=new PC();
sm.显示商标("联想奔月5008");
}
}
interface Computable
{
public double 求面积();
}
class 梯形 implements Computable
{double a,b,h;
梯形(double a,double b,double h)
{this.a=a;
this.b=b;
this.h=h;
}
public double 求面积()
{return((1/2.0)*(a+b)*h);
}
}
class 圆形 implements Computable
{double r;
圆形(double r)
{this.r=r;
}
public double 求面积()
{return(3.14*r*r);
}
}
class 堆
{Computable 底;
double 高;
堆(Computable 底,double 高)
{ this.底=底;
this.高=高;
}
void 换底(Computable 底)
{this.底=底;
}
public double 求体积()
{return (底.求面积()*高)/3.0;
}
}
public class Example418
{public static void main(String args[])
{堆 zui;
Computable tuxing;
tuxing=new 梯形(2.0,7.0,10.7);
System.out.println("梯形的面积"+tuxing.求面积());
zui=new 堆(tuxing,30);
System.out.println("梯形底的堆的体积"+zui.求体积());
tuxing=new 圆形(10);
System.out.println("半径是10的圆的面积"+tuxing.求面积());
zui.换底(tuxing);
System.out.println("圆形底的堆的体积"+zui.求体积());
}
}
定义一个接口变量 将子类对象的引用 也就是new xx();传递给此接口变量就是接口回调 和类的上转型对象差不多
接口做参数
如果一个方法的参数是接口类型 就可以将任何实现该接口类型的实例的引用传递给该接口参数 那么接口参数就可以回调类实现的接口的方法
interface Speakhello
{void speakhello();
}
class Chinese implements Speakhello
{public void speakhello()
{System.out.println("中国人的习惯问候语就是你好 吃饭了吗?");
}
}
class English implements Speakhello
{public void speakhello()
{System.out.println("英国人的习惯就是你好,天气不错");
}
}
class Kindhello
{public void lookhello(Speakhello hello)
{hello.speakhello();
}
}
public class Example419
{public static void main(String arg[])
{Kindhello kindhello=new Kindhello();
kindhello.lookhello(new Chinese());
kindhello.lookhello(new English());
}
}
Java支持在类中声明另一个类 这样的类称之为内部类 包含内部类的类称为内部类的外嵌类 声明内部类和声明类中的方法是一样的 一个类吧内部类看做是自己的成员 内部类的外嵌类的成员变量和在内部类中依然有效 内部类的方法也可以调用外部类的方法
内部类的类体不可以声明类变量和类方法 外嵌类可以使用内部声明对象 作为外嵌套类的成员
class China
{final String nationalAnthem="义勇军进行曲";
Beijing beijing;
China()
{beijing=new Beijing();
}
String getsong()
{return nationalAnthem;
}
class Beijing
{String name="北京";
void speak()
{System.out.println("我们是"+name+"我们的国歌是"+getsong());
}
}
}
public class Example420
{public static void main(String args[])
{China china=new China();
china.beijing.speak();
}
}
当使用类创建对象的时候程序允许把类体和对象的创建组合在一起 也就是说 在创建对象时候 除了构造方法还有类体 此类体被认为是去掉类声明的类体 成为匿名类
注意:匿名类的名称呢是对象的引用 但是类体呢 是没有去掉声明的类体
New people (){类体} 匿名类一定是内部类可以继承也可以重写父类的方法 使用匿名类时候必须在某个类中直接用匿名类创建对象 匿名类可以访问外嵌类的变量和方法 匿名类的类体中不可以声明static变量和方法
尽管匿名类创建的对象没有经过声明 但是匿名对象的引用必须传递一个匹配的参数 匿名类的主要作用就是向方法传的参数传值
Void f(B b){ x调用B }类中的方法
其中参数是B类对象 呢么在调用方法f的时候 可以向其参数传递一个匿名对象
f(new B())
{匿名类的类体}
class Cubic
{ double getCubic(int n)
{ return 0;
}
}
abstract class Sqrt
{ public abstract double getSqrt(int x);
}
class A
{ void f(Cubic cubic) //定义一个匿名类
{ double result=cubic.getCubic(3);//执行匿名类中重写的方法
System.out.println(result);
}
}
public class Example421
{ public static void main(String args[])
{ A a=new A();
a.f(new Cubic()
{ double getCubic(int n)
{ return n*n*n;
}
}
);
Sqrt ss=new Sqrt() //迷惑所在 抽象类的匿名类???
{ public double getSqrt(int x)
{ return Math.sqrt(x);
}
};
double m=ss.getSqrt(5);
System.out.println(m);
}
}
和接口有关的匿名类 java允许接口名和类体创建一个匿名对象 此类体就被认为实现了接口的类去掉类声明的类体 成为匿名类 如果某个方法的参数是接口类型的 那么可以使用接口名和类体组合创建一个匿名类传递给方法的参数 类体必须实现接口中的所有方法
interface Cubic
{ double getCubic(int n);
}
interface Sqrt
{ public double getSqrt(int x);
}
class A
{ void f(Cubic cubic)
{ double result=cubic.getCubic(3);
System.out.println(result);
}
}
public class Example4_32
{ public static void main(String args[])
{ A a=new A();
a.f(new Cubic()
{ public double getCubic(int n)
{ return n*n*n;
}
}
);
Sqrt ss=new Sqrt()
{ public double getSqrt(int x)
{ return Math.sqrt(x);
}
};
double m=ss.getSqrt(5);
System.out.println(m);
}
}
所谓异常就是指程序运行的时候会产生一些错误 但是不是致命的错误 当程序出现异常的时候 java运行环境就用异常类exception的相应子类创建一个对象 并等待处理
异常对象可以调用以下方法得到或者输出有关异常的信息
Public string getmessage() public void printstacktrace() public string tostring()
Java使用try catch语句处理异常 try 部分语句发生异常的时候 try部分立即结束 转向执行catch语句中部分 所以程序将发生异常后的处理放在catch中 可以看成是有些时候if else
Try{包中可能发生的异常}
Catch(exceptionsubclass1 e){}
public class Example422
{ public static void main(String args[ ])
{ int n=0,m=0,t=555;
try{ m=Integer.parseInt("8888");
n=Integer.parseInt("abc789");
t=9999;
}
catch(NumberFormatException e)
{ System.out.println("发生异常:"+e.getMessage());
e.printStackTrace();
n=123;
}
System.out.println("n="+n+",m="+m+",t="+t);
}
}
自定义异常类
可以在程序中扩展exception定义自己的异常类 然后规定哪些方法产生这些异常类 一个方法在声明的时候可以使用throws关键字来声明要产生的若干异常 并在方法体重具体给出产生异类的操作 即用相应的异常类创建对象 并使用throw关键字抛出该异常类 导致该方法结束执行 程序必须在trycatch语句中调用能发生异常的方法 其中catch的作用就是捕获throw关键字抛出的异常对象
class NopositiveException extends Exception
{ String message;
NopositiveException(int m,int n)
{ message="数字"+m+"或"+n+"不是正整数";
}
public String toString()
{ return message;
}
}
class Computer
{ public int getMaxCommonDivisor(int m,int n) throws NopositiveException
{ if(n<=0||m<=0)
{ NopositiveException exception=new NopositiveException(m,n);
throw exception;
}
if(m
{ int temp=0;
temp=m;
m=n;
n=temp;
}
int r=m%n;
while(r!=0)
{ m=n;
n=r;
r=m%n;
}
return n;
}
}
public class Example423
{ public static void main(String args[])
{ int m=24,n=36,result=0;
Computer a=new Computer();
try { result=a.getMaxCommonDivisor(m,n);
System.out.println(m+"和"+n+"的最大公约数 "+result);
m=-12;
n=22;
result=a.getMaxCommonDivisor(m,n);
System.out.println(m+"和"+n+"的最大公约数 "+result);
}
catch(NopositiveException e)
{ System.out.println(e.toString());
}
}
}
该方法具体给出产生异常的操作 即用相应的异常类创建对象 并使用throw关键字抛出该异常类对象
Class 的实例来封装对象运行时的状态当一个 类被加载时候和该相关的class类的对象就会自动创建 class类本身不提供构造方法 因此 不能使用new运算符和构造方法创建一个class对象 任何对象调用getclass()方法都可以获取和该对象相关的一个class对象
这个class对象调用以下方法可以获得创建对象的类的有关信息
String getniame() ;constructor[] getdeclaredconstrucors();返回所有的构造方法
Field[] getdeclareddfield()返回类的全部成员变量
Method[] getdeclaredmethods();返回类的全部方法
import java.lang.reflect.*;
class Rect
{ double width,height,area;
public double getArea()
{ area=height*width;
return area;
}
}
public class Example424
{ public static void main(String args[])
{ Rect rect=new Rect();
Class cs=rect.getClass();// 任何对象调用getclass()方法都可以获取和该对象相关的一个class对象
String className=cs.getName();
Constructor[] con=cs.getDeclaredConstructors();
Field[] field=cs.getDeclaredFields() ;
Method[] method=cs.getDeclaredMethods();
System.out.println("类的名字:"+className);
System.out.println("类中有如下的成员变量:");
for(int i=0;i
{ System.out.println(field[i].toString());
}
System.out.println("类中有如下的方法:");
for(int i=0;i
{ System.out.println(method[i].toString());
}
System.out.println("类中有如下的构造方法:");
for(int i=0;i
{ System.out.println(con[i].toString());
}
}
}