访问控制与封装
访问控制与封装
1 package包
1.1 什么是package
Java中利用package对类进行分类,方便管理代码,package还定义了命名空间,减少了命名冲突,不同的包中可以定义同名类。
使用包:
- 必须在Java源文件的第一行使用package声明包,package语句只能有一行
- package可以不写,不写表示使用默认包
- package相同的类放置在同一个包中
- 包名要符合java命名规范(包名采用小写字母)
- 一个包中可以定义多个类,但是类名不能同名
- 包编译以后变成多对应的文件夹
1.2 全限定名和import
全限定名:也称为全名,是指由包名和类名组成的完整名称。遇到相同类名时候不能省略包名。
案例:
package demo02;
public class Foo{
}
package demo03;
public class Foo{
}
package demo01;
public class Demo01{
public static void main(String[] args){
//使用全限定名访问其他包中的类
demo02.Foo foo=new demo02.Foo();
demo03.Foo foo2=new demo03.Foo();
}
}
package demo01;
import demo02.Foo;
//import Demo02.Foo;//在Java源文件中不能同时导入同名类
public class Demo01{
public static void main(String[] args){
/*
*使用import导入其他包中的类,可以直接使用,不需要全限定名
*/
Foo foo=new Foo();
//如果需要在一个源文件中使用两个同名类,就必须使用全限定名访问
demo03.Foo foo2=new demo03.Foo();
}
}
2 访问控制与封装
2.1 什么是访问控制
访问控制:用于设定类,属性,方法等资源的可见范围。利用访问控制可以控制数据及方法的可见范围,避免意外篡改,保护软件组件(对象)的安全可靠。
2.2 访问控制修饰词属性
4个访问修饰词:
- public 公有的,修饰类,修饰属性,修饰方法,修饰构造器
- protected 保护的,修饰类中的成员:属性,方法,构造器等
- 默认的,不写任何修饰词,修饰类,修饰属性,修饰方法,修饰构造器
- private 私有的,修饰类中的成员:属性、方法、构造器等
2.3 public和private
public 是公有的,其可见范围最大,被修饰资源可以在任何位置使用
private是私有的,其可见范围最小,被修饰的资源仅仅在当前类体内部可见。
案例:+
package demo04;
public class Goo{
private int a=6;
public int b=5;
public int add(){
//私有属性a可以在类内部访问,属性a属于当前类私有
return a+b;
}
}
package demo05;
import demo04.Goo;
public calss Demo04{
public static void main(String[] args){
/*
*测试public和private的区别
*/
Goo goo=new Goo();
//System.out.println("goo.a");//编译错误,不可见
System.out.println("goo.b");//公有属性可以访问
System.out.println("goo.add");//公有方法可以访问
}
}
2.4 public 与默认
案例:
package demo06;
public calss Koo{
int a=6;//默认修饰
public int b=5;//公有修饰
}
package demo06;
public class Demo05{
public static void main(String[] args){
/*
*访问公有和默认的属性
*/
Koo koo=new Koo();
//同一个包demo06中可以访问默认属性
System.out.println("koo.a");
//同一个包中也可以访问公有属性
System.out.println("koo.b");
}
}
package demo07;
import demo06.Koo;
public class Demo06{
public static void main(String[] args){
/*
*访问公有和默认的属性
*/
Koo koo=new Koo();
//不在同一个包demo06中不能访问默认属性
System.out.println("koo.a");
//同一个包中也可以访问公有属性
System.out.println("koo.b");
}
}
2.5 protected与默认
protected修饰的资源其可见范围是子类和当前包内部可见,子类“泛化”到父类中的属性和方法经常定义为保护的。
package demo08;
public class Xoo{
protected int a=6;//保护属性
int b=8;//默认属性
}
package demo08;
public class Demo07{
public static void main(String[] args){
/*
*在同一个包中访问默认和保护的属性
*/
Xoo xoo=new Xoo();
System.out.println("Xoo.a");
System.out.println("Xoo.b");
}
}
package demo09;
import demo08.Xoo;
public class Demo08{
public static void main(String[] args){
/*
*不在同一个包的时候,访问另一个包中的默认和保护属性
*/
Xoo xoo=new Xoo();
//默认和保护的属性都是包内可见
//System.out.println("Xoo.a");//不可见
//System.out.println("Xoo.b");//不可见
}
}
package demo09;
import demo08.Xoo;
public class Yoo extends Xoo{
public void test(){
//在子类中可以访问继承到的保护属性
System.out.println(a);
//默认属性,不支持跨包访问
System.out.println(b);
}
public static void main(String[] args){
Yoo yoo=new Yoo();
yoo.test();
}
}
2.6 封装
面向对象三大基本特征:封装,继续,多态。
封装是指:一种将抽象性函数接口的实现细节部分包装、隐藏起来的方法。也是一种防止外界调用端,去访问对象内部实现细节的手段。
简单理解:封装数据和算法细节,暴露可以安全访问的方法和数据。
Java中的封装就是采用访问修饰词实现的:
- 需要隐藏的属性和方法定义为私有的private
- 需要留给子类使用的属性和方法定义为保护的protected
- 确实需要公开访问的属性和方法定义公有的public
- 默认的访问控制不使用
2.7 飞机大战中的封装
案例:
package demo10;
import java,awt.Graphics;
import javax.swing.ImageIcon;
/*
* 父类中定义从子类抽取的属性和方法
* 这种抽取方式称为“泛化”
*/
public class FlyingObject {
protected double x;
protected double y;
protected double width;
protected double height;
protected double step;
protected ImageIcon image;
public FlyingObject(double x, double y, double width, double height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public void move(){
y+=step;
}
public void paint(Graphics g){
image.paintIcon(null,g,(int)x, (int)y);
}
@Override
public String toString() {
String className=getClass().getName();
return className+" [x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + "]";
}
}
package demo10;
import java.awt.Graphics;
import javax.swing.ImageIcon;
public class Sky extends FlyingObject{
protected double yo;
public Sky(double x, double y, double width, double height, double step) {
super(x,y,width,height);
this.step =step;
this.image=new ImageIcon("images/background.png");
x=0;
y=0;
yo=-image.getIconHeight();//照片的高度
height=image.getIconHeight(); //天空的高度(照片)
width=image.getIconWidth();//天空的宽度(照片)
System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
}
public void move() {
y+=step;
yo+=step;//(两个坐标都在移动)
if(y>=height) {
//System.out.println("第一个照片返回:y="+y);
y=-height;
//System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
}
if(yo>=height) {
//System.out.println("第二个照片返回:y0="+yo);
yo=-height;
//System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
}
}
public void paint(Graphics g) {//改写父类中的方法
image.paintIcon(null, g, (int)x, (int)y);
image.paintIcon(null, g, (int)x, (int)yo);//对天空做修改,对两张照片进行处理
}
}
package demo10;
import java.awt.Graphics;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class World extends JPanel{
/*
* 添加飞机大战世界中的物体
*/
private Airplane[] airplanes;
private Bigplane[] bigplanes;
private Bullet[]bullets;
private Sky sky;
private Hero hero;
/*
* 利用构造器初始化世界中每个物体
*/
public World(){
airplanes=new Airplane[2];//创建两个元素的数组
airplanes[0]=new Airplane(10,10,1.5);//宽高去掉了50,40
airplanes[1]=new Airplane(10,100,1.5);
//x,y 宽 高 速度
bigplanes=new Bigplane[2];
bigplanes[0]=new Bigplane(100,20,2);//宽高去掉了100,200
bigplanes[1]=new Bigplane(100,220,2);
bullets =new Bullet[6];
bullets[0]=new Bullet(200,400,4);//宽高去掉了10,10
bullets[1]=new Bullet(200,350,4);
bullets[2]=new Bullet(200,300,4);
bullets[3]=new Bullet(200,250,4);
bullets[4]=new Bullet(200,200,4);
bullets[5]=new Bullet(200,150,4);
sky=new Sky(0,0,400,700,0.8);
hero=new Hero(200,500,200,200);
}
public void paint(Graphics g) {
sky.paint(g);
hero.paint(g);
for(int i=0; i<bullets.length; i++) {
//i=0 1 2 3 4 5
bullets[i].paint(g);
}
//调用每个飞机的多态方法,实现多态的绘制
for(int i=0; i<planes.length; i++) {
airplanes[i].paint(g);
}
for(int i=0; i<planes.length; i++) {
bigplanes[i].paint(g);
}
}
public static void main(String[] args) {
JFrame frame=new JFrame();
World world=new World();
frame.add(world);
frame.setSize(400,700);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//调用action方法启动定时器
world.action();
}
/*
* 添加内部类,实现定时计划任务
* 为何使用内部类实现定时任务
* 1.隐藏定时任务到world类中
* 2.可以访问外部类中的数据,飞机,子弹等
*/
private class PaintTask extends TimerTask{
public void run(){//执行飞机移动方法;是多态的移动方法,每个飞机都不同
for(int i=0; i<airplanes.length; i++){
airplanes[i].move();
}
for(int i=0; i<bigplanes.length; i++){
bigplanes[i].move();
}
for(int i=0; i<bullets.length; i++){
bullets[i].move();
}
sky.move();
repaint(); //调用重写绘制方法,这个方法会自动执行paint
}
}
public void action(){//启动方法
Timer timer=new Timer();
PaintTask task=new PaintTask();//定时器任务
timer.schedule(task,1000,1000/100);//规定计划每间隔多少时间执行
}
}
访问控制与封装
3 final最终
Java中final可以修饰变量,修饰方法,修饰类
- 变量:可以初始化,不能再更改‘
- 方法:不能在子类中重写
- 类:不能再被继承派生出子类了
3.1 final局部变量
在方法中声明的变量称为局部变量。只能初始化一次,不能再更改,目的是保护局部变量的值不变,避免篡改。
package demo11;
import java.util,Arrays;
public class Demo01 {
public static void main(String[] args) {
/*
* final局部变量现象
*/
final int a;
a=8;//第一次为变量赋值,称为初始化
System.out.println(a);
//a=9;//编译错误,a不能再次被修改
final int b=9;//声明变量直接初始化
System.out.println(b);
//b=10;//不能再次修改final变量
int c=8;
c=6;
System.out.println(c);//6
final int C=300000;
//C++;不能再修改变量C
System.out.println(C);
//final修饰的引用类型变量
//引用类型变量初始为一个地址值后不能再次修改
final int[] arr= {5,6};//arr中储存的数组地址不能再次修改类
//arr引用不能修改,但是被引用对象内容可以修改
arr[0]=9;
System.out.println(Arrays.toString(arr));//[9,6]
//不可以更改arr变量的值,因为arr是final类型的
//arr=new int [8];
final Ball ball=new Ball();
ball.d=10;
System.out.println(ball.d);
//不能更换ball的值,也就是地址值
//ball=null;
final Girl gf=new Girl();
gf.age++;//年龄可增长
System.out.println(gf.age);
//gf=new Girl();对象不能变
}
}
class Girl{
int age=18;
}
class Ball{
int d=5;
}
3.2 final修饰方法参数
public class Demo2 {
public static void main(String[] args) {
/*
* final修饰的方法参数
* 1,方法参数是局部变量,在传递参数时初始化
* 2,final 的方法参数,在接受参数初始化以后不能再次修改
*/
test(5,6);
test(7,8);
}
public static void test(int a, final int b) {
a=9;
//b=8;//编译错误,不能再次更改变量b
System.out.println("a:"+a+",b:"+b);//a=9,b=6//a=9,b=8
}
}
3.3 final修饰实例变量
在类中声明的对象属性称为“实例变量”。实例变量在初始化后不能再次改变。目的也是保护实例变量。
案例:
package demo11;
public class Demo3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 演示final的实例变量(对象属性)
*/
Eoo eoo=new Eoo(8);
System.out.println(eoo.a);//5
System.out.println(eoo.b);//8
//不能再次更改final的实例变量
//eoo.a=9;
//eoo.b=9;
Eoo e2=new Eoo(10);
System.out.println(e2.a);//5
System.out.println(e2.b);//10
}
}
class Eoo{
//final的属性必须初始化
final int a=5;
final int b;
public Eoo(int b) {
this.b=b;
}
}
3.4 final方法
final的方法在子类中不能被重写修改。
简单理解:final方法不能被重写,final修饰的方法不会影响方法在当前类中的使用,但是如果派生了子类,则在子类中不能重写修改父类中定义的final方法。
案例:
package demo11;
public class Demo4 {
public static void main(String[] args) {
/*
* final方法可以被子类继承,但是不能被子类重写
*/
Foo foo=new Foo();
foo.test();
SubFoo sf=new SubFoo();
sf.test();
}
}
class Foo{
public final void test() {
System.out.println("Foo.test()");
}
}
class SubFoo extends Foo{
//public void test();编辑错误,不能重写FOO中的final方法
// System.out.println("SubFoo.test()");
}
3.5 final类
final类不能被继承。
package demo11;
public class Demo5 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 测试final类
*/
Goo goo=new Goo();
goo.test();
}
}
final class Goo{
public void test() {
System.out.println("test()");
}
}
//class SubGoo extends Goo{//编译错误,不能继承final类
}
3.6 final总结
- 变量:可以初始化,不能再更改,很常用
- 方法:不能在子类中重写,不常用
- 类:不能再被继承派生出子类了,不常用
4 静态
static翻译为静态,可以修饰成员变量、方法,可以与final联合使用修饰常量。
4.1 成员变量
三种:
- 实例变量:属于每个对象属性,每个对象中都有一份
- 静态变量:属于类的变量,只有一份,全体对象共享的同一份变量
- 常量:不变的常数
成员变量:
class Foo{
int a=5;//实例变量
static int b=6;//静态变量
static final int c=30;//常量
}
4.2 静态变量
软件中只有一份的数据应该使用ststic修饰。
package demo12;
public class Demo01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 演示静态变量功能
* 实例变量a;每个对象都有一个实例变量
* 静态变量b;属于类的一份变量,全体对象共享同一个b
*/
Foo h1=new Foo();
Foo h2=new Foo();
h1.a=8;
h2.a=10;
Foo.b =11;//使用类名访问静态变量
System.out.println(h1.a+","+h1.b);//8,11
System.out.println(h2.a+","+h2.b);//10,11
System.out.println(Foo.b);//11,读取静态变量
}
}
class Foo{
int a;//实例变量
static int b;//静态变量
}
4.3静态变量工作原理
-
Java源文件经过编译得到字节码文件,每个类编译为一个class文件
-
当执行Java程序时候,每用到一个类Java就会自动将对应的字节码加载到方法区
- 创建对象时会自动加载类
- 访问类的静态属性时候会自动加载类
- 执行类中的静态方法时候会自动加载类
- 字节码文件只加载一次
-
如果类中有静态变量,Java就会在加载类期间将其在方法区中分配出来,静态变量也初始化一次,只有一份
-
创建对象时候按照类中声明的实例变量分配对象的属性,每创建一个对象,就会分配一组对象属性。
4.4 静态方法
静态方法就是在声明方法时候添加static关键字。可以直接使用类名直接引用方法。
静态方法没有隐含的局部变量this,对象方法中保护隐含局部变量this。
静态方法不能访问实例变量和对象方法,因为main方法也是静态方法,所有main方法也不能访问当前类型的实例变量和对象方法。
案例:
package demo12;
public class Demo02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
/*
* 静态方法演示
*/
Person.add(7,8);//用类名调用静态方法
Person tom=new Person("Tom");
tom.whoru();//用对象引用调用对象的方法
}
}
class Person{
String name;
public Person(String name) {
this.name=name;
}
public void whoru() {
//对象方法中包含隐含局部变量this
System.out.println("我是"+this.name);//Tom
}
//如果方法中没有用到当前对象的属性/方法就声明为static
public static void add(int a, int b) {
//静态方法中没有隐含局部变量this
System.out.println(a+b);//15
}
}
4.5 静态代码块
用于初始对象属性(很少使用)
class Cell{
int a;
{
//代码块,在创建对象时执行
a=(int)(Math.random()*8);
}
}
package demo12;
public class Demo03 {
public static void main(String[] args) {
/*
* 测试静态代码块
* java会在创建对象之前自动加载类Circle
*/
Circle c1=new Circle();
Circle c2=new Circle();
System.out.println(Circle.angle);
}
}
class Circle{
static double angle;//角
static {//在类加载期间执行,只执行一次
System.out.println("初始化angle");
angle=Math.PI*2;
}
}
4.6 static final
常量用于声明不会变化的量。
软件中的常量:
- 软件中不能改变的数据都应定义为常量
- 同时使用static final修饰,顺序可以调换
- 常量必须初始化
- 一般变量名都是大写字母,多个单词使用下划线隔开:Max_VALUE
Java APL提供很多常量:
- Math.PI、Math.E
- integer.MAX_VALUE、integer.MIN_VALUE
- Long.MAX_VALUE、Long.MIN_VALUE
4.7静态导入
import static称为静态导入:
import static java.lang.Math.PI;
import static java.lang.Math.sin;
import static java.lang.Math.*;
Java 8 提供了静态导入语法,用于简化静态资源的编码。
package demo11;
public class Demo04 {
public static void main(String[] args) {
/*
*输出30,60,75,90的正弦值
*Math.sin()正弦函数,参数必须是弧度
*Math.toRadians()角度转换函数,将角度转换为弧度
*PI/2是90度角
*/
System.out.println(Math.sin(Math.toRadians(30)));
System.out.println(Math.sin(Math.toRadians(60)));
System.out.println(Math.sin(Math.toRadians(75)));
System.out.println(Math.sin(Math.toRadians(90)));
System.out.println(Math.sin(Math.PI/2));
}
}
采用静态导入解决冗余繁琐:
package demo11;
import static java.lang.Math.*;
public class Demo05 {
public static void main(String[] args) {
System.out.println(sin(toRadians(30)));
System.out.println(sin(toRadians(60)));
System.out.println(sin(toRadians(75)));
System.out.println(sin(toRadians(90)));
System.out.println(sin(PI/2));
}
}
5 重构飞机大战
5.1 声明images类
实现思路:由于图片属于静态资源,加载一份以后为与各种飞行物进行共享即可,再基于功能分治的原则进行设计
-
设计一个图片资源管理类images,在images中定义静态变量管理图片
-
在images中添加静态代码块,用于初始化静态图片资源
a.单张图片利用静态图片变量储存
b.多张图片利用静态图片数组储存
-
对图片资源加载结果进行单元测试
package demo13;
import javax.swing.ImageIcon;
public class Images {//管理图片
public static ImageIcon[] airplane;
public static ImageIcon[] bigplane;
public static ImageIcon[] bee;
public static ImageIcon bullet;
public static ImageIcon[] hero;
public static ImageIcon[] bom;
public static ImageIcon sky;
public static ImageIcon start;
public static ImageIcon pause;
public static ImageIcon gameover;
static {//先创建数组,然后对数组初始化
airplane=new ImageIcon[2];
airplane[0]=new ImageIcon("images/airplane0.png");
airplane[1]=new ImageIcon("images/airplane1.png");
bigplane=new ImageIcon[2];
bigplane[0]=new ImageIcon("images/bigairplane0.png");
bigplane[1]=new ImageIcon("images/bigairplane1.png");
bee=new ImageIcon[2];
bee[0]=new ImageIcon("images/bee0.png");
bee[1]=new ImageIcon("images/bee1.png");
bullet=new ImageIcon("images/bullet.png");
hero=new ImageIcon[2];
hero[0]=new ImageIcon("images/hero0.png");
hero[1]=new ImageIcon("images/hero1.png");
bom=new ImageIcon[4];
bom[0]=new ImageIcon("images/bom1.png");
bom[1]=new ImageIcon("images/bom2.png");
bom[2]=new ImageIcon("images/bom3.png");
bom[3]=new ImageIcon("images/bom4.png");
sky=new ImageIcon("images/background.png");
start=new ImageIcon("images/start.png");
pause=new ImageIcon("images/pause.png");
gameover=new ImageIcon("images/gameover.png");
}
public static void main(String[] args) {
//单元测试方法
System.out.println(airplane[0].getImageLoadStatus());//8
System.out.println(airplane[1].getImageLoadStatus());//8
System.out.println(bigplane[0].getImageLoadStatus());//8
System.out.println(bigplane[1].getImageLoadStatus());//8
System.out.println(bee[0].getImageLoadStatus());//8
System.out.println(bee[1].getImageLoadStatus());//8
System.out.println(bullet.getImageLoadStatus());//8
System.out.println(hero[0].getImageLoadStatus());//8
System.out.println(hero[1].getImageLoadStatus());//8
System.out.println(bom[0].getImageLoadStatus());//8
System.out.println(bom[1].getImageLoadStatus());//8
System.out.println(bom[2].getImageLoadStatus());//8
System.out.println(bom[3].getImageLoadStatus());//8
System.out.println(sky.getImageLoadStatus());//8
System.out.println(start.getImageLoadStatus());//8
System.out.println(pause.getImageLoadStatus());//8
System.out.println(gameover.getImageLoadStatus());//8
}
}
5.2 重构飞机大构造器
将加载图片更换成从images获得图片。
子弹:
package demo13;
public class Bullet extends FlyingObject{
public Bullet(double x, double y, double width, double height, double step) {
//利用super()调用父类有参数构造器,复用了父类中构造器算法
super(x,y,width,height);
this.step = step;
image=Images.bullet;
width=image.getIconWidth();
height=image.getIconHeight();
}
/**
*重写继承与超类的move方法,作用就是修改了超类move行为
*超类是向下移动,修改为向上移动
*/
public void move(){
y-=step;
}
}
小飞机:
package demo13;
public class Airplane extends FlyingObject{
public Airplane(double x, double y, double width, double height, double step) {
//利用super()调用父类有参数构造器,复用了父类中构造器算法
super(x,y,width,height);
this.step = step;
image=Images.airplane[0];
width=image.getIconWidth();
height=image.getIconHeight();
}
}
大飞机:
package demo13;
public class Bigplane extends FlyingObject{
public Bigplane(double x, double y, double width, double height, double step) {
//利用super()调用父类有参数构造器,复用了父类中构造器算法
super(x,y,width,height);
this.step = step;
this.image=Images.bigplane[0];
width=image.getIconWidth();
height=image.getIconHeight();
}
}
蜜蜂:
package demo13;
public class Bee extends FlyingObject{
public Bee(double x, double y, double width, double height, double step){
super(x,y,width,height);
this.step=step;
this.image=Images.bee[0];
width=image.getIconWidth();
height=image.getIconHeight();
}
/**
*重写父类型move方法修改为斜向飞行
*/
public void move(){
//调用父类型方法,复用父类型定义的算法
super.move();//向下飞行
x++;
}
}
英雄:
package demo13;
public class Hero extends FlyingObject{
public Hero(double x, double y, double height, double width) {
super(x,y,width,height);
this.image=Images.hero[0];
width=image.getIconWidth();
height=image.getIconHeight();
}
/*
* 重写move方法,空方法,目的是不动
* 修改超类中规定的向下飞,改成不动
*/
public void move() {
}
/*
*将鼠标机移动到鼠标位置X,Y
*@param x鼠标位置x
*@param y鼠标位置y
*/
public void move(int x, int y) {
this.x=x;
this.y=y;
}
}
天空:
package demo13;
import java.awt.Graphics;
import javax.swing.ImageIcon;
public class Sky extends FlyingObject{
protected double yo;
public Sky(double x, double y, double width, double height, double step) {
super(x,y,width,height);
this.step =step;
this.image=Images.sky;
x=0;
y=0;
yo=-image.getIconHeight();//照片的高度
height=image.getIconHeight(); //天空的高度(照片)
width=image.getIconWidth();//天空的宽度(照片)
System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
}
public void move() {
y+=step;
yo+=step;//(两个坐标都在移动)
if(y>=height) {
//System.out.println("第一个照片返回:y="+y);
y=-height;
//System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
}
if(yo>=height) {
//System.out.println("第二个照片返回:y0="+yo);
yo=-height;
//System.out.println("y="+y+" y0="+yo+" width="+width+" height="+height);
}
}
public void paint(Graphics g) {//改写父类中的方法
image.paintIcon(null, g, (int)x, (int)y);
image.paintIcon(null, g, (int)x, (int)yo);//对天空做修改,对两张照片进行处理
}
}