Java面向对象程序设计第6章1-12
- 2019 年 10 月 9 日
- 笔记
1.this和super各有几种用法?
this
this 用法有三种,主要应用场合:
-
表示当前对象引用,常用于形参或局部变量与类的成员变
量同名的情形,使用this.成员名表示当前对象的成员
- 表示当前对象
-
class FighterPlane { private String name; private int missileNum; private A a; public void setA(A _a){ if (_a !=null) { a = _a ;} } public A getA(){ if (a !=null) { return a;} else return null; } public void fire(){ ……} public FighterPlane(String _name,int _missileNum){ ……} } class A { FighterPlane fp; public A(FighterPlane fpp){ this.fp = fpp; fpp.setA(this);//将当前对象传给FighterPlane } public void invoke(){ //A中对象发送消息给FighterPlane的对象 fp.fire(); } } public class Run{ public static void main(String[] args) { FighterPlane ftp = new FighterPlane("su35",10); A a = new A(ftp); a.invoke(); } }
- 调用当前类的构造方法
class AddClass { public int x=0,y=0,z=0; AddClass (int x) { this.x=x; } AddClass (int x,int y) { this(x); this.y=y; } AddClass (int x,int y,int z) { this(x,y); this.z=z; } public int add() {return x+y+z; } } public class RunAddClass { public static void main(String[] args) { AddClass p1=new AddClass(2,3,5); AddClass p2=new AddClass(10,20); AddClass p3=new AddClass(1); System.out.println("x+y+z="+p1.add()); System.out.println("x+y="+p2.add()); System.out.println("x="+p3.add()); } }
super
super访问当前类的直接父类,主要应用场合:
-
子类的数据成员或成员方法与父类的数据成员或成员方法名
字相同时,当要调用父类的同名方法或同名数据成员时则可
用super来指明。即super.数据成员;super.成员方法
-
super(参数) , 表示调用父类构造方法
class A { int x=4;int y=1; public void Printme() { System.out.println("x="+x+" y="+y); System.out.println("class name: "+getClass().getName()); } } public class AA extends A{ int x; public void Printme() { int z=super.x+6; super.x = 5; super.Printme(); System.out.println("I am an "+getClass().getName()); x=6; System.out.println(" z="+z+" x="+x+" super.x="+super.x +" y="+y+"super.y="+y); } } public static void main(String arg[]) { int k; A p1=new A(); AA p2=new AA(); p1.Printme(); p2.Printme(); } }
注意:
-
子类和父类定义了同名数据成员,子类继承了父类的x,自
己又定义了一个x,则会发生父类数据成员的隐藏。在子类
中用的x都是子类自己的,若要使用父类x,则必须用super.x。
-
子类在覆盖父类方法的同时,调用父类的super.Printme(),这
个方法中的成员变量均为父类的成员变量。super.Printme()中
的代码虽然调用父类代码,但其中的this指的是子类对象。
2.子类对象实例化的具体过程是什么?
- 子类在构造对象时候,必须访问父类的构造函数,为了完成这个必须的动作,就在子类的构造函数中加入了super()语句。
- 如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用父类中哪个构造函数,否则子类无法完成初始化。
- 在构造函数生效之前,程序会先执行静态的成员活方法的初始化。
3.类的域变量和方法中定义的局部变量在初始化上有何区别?
类的域变量在类初始化的时候就开始创建了,而方法中的变量是在调用到该方法时,才会为该变量创建。
4.模仿形成抽象类的过程,自选角度,形成一个自己的抽象类,并在程序的类继承和引用中体现抽象类的作用。
import java.awt.*; import java.applet.*; //抽象类Shapes abstract class Shapes { protected int x,y,k; protected double m; public Shapes(int x,int y,int k,double m){ this.x=x; this.y=y; this.k=k; this.m=m; } abstract public double getArea(); abstract public double getPerimeter(); } //各子类定义 class Rect extends Shapes { public double getArea() { return(k*m); } public double getPerimeter() { return(2*k+2*m);} public Rect(int x,int y,int width,int height) { super(x,y,width,height);} } class Triangle extends Shapes{ public double getArea(){ return(Math.sqrt(m*( m-k)*( m-x)*(m-y)));} public double getPerimeter(){ return(k+x+y);} public Triangle(int baseA,int baseB,int baseC){ super(baseA, baseB, baseC,0); //m充当了周长的一半 m= (baseA+ baseB+ baseC)/2.0; } } class Circle extends Shapes{ public double getArea() //Math是java.lang包中的类,PI是静态其属性,其值为Π { return(m* m *Math.PI);} public double getPerimeter() {return(2*Math.PI* m);} public Circle(int x,int y,int width){ //k充当了直径,m充当了半径的角色 super(x,y, width, width/2.0); } } //使用类 public class RunShape extends Applet{ Rect rect=new Rect(5,15,25,25); Triangle tri=new Triangle(5,5,8); Circle cir =new Circle(13,90,25); public void paint(Graphics g){ //绘制矩形,输出矩形的面积和周长 g.drawRect(rect.x,rect.y,rect.k,(int)rect.m); g.drawString("Rect Area:"+rect.getArea(),50,35); g.drawString("Rect Perimeter:"+rect.getPerimeter(),50,55); //输出三角形的面积和周长 g.drawString("Triangle Area:"+tri.getArea(),50,75); g.drawString("Triangle Perimeter:"+tri.getPerimeter(),50,95); //绘制圆,输出圆的面积和周长 g.drawOval(cir.x-(int)cir.k/2,cir.y-(int)cir.k/2,cir.k,cir.k); g.drawString("Circle Area:"+cir.getArea(),50,115); g.drawString("Circle Perimeter:"+cir. getPerimeter(),50,135); } }
5.接口有什么作用?自己定义一个接口,并给出实现类和使用类。
接口的两种含义:
- 可以被引用调用的方法(public方法或同包中的protected方法或默认方法);
- 另一种是同“类”概念地位相当的专有概念interface, interface是方法说明的集合。
作用:
接口最直接的好处就是提供了一个统一的操作方法名,然后同样的方法名在不同的类中可以有不同的具体实现过程,这样的结果就是在操作实现了该接口的类的对象时,不用去事先了解该方法的名字,而采用统一的名字进行调用。
接口的设计用途:通用可扩展代码,多态体现
import java.util.*; public boolean addAll(int index, Collection c) { int numNew = c.size(); ...... } public boolean addAll(int index, AbstractCollection c) public boolean addAll(int index, AbstractList c) public boolean addAll(int index, AbstractSet c) public boolean addAll(int index, LinkedList c) public boolean addAll(int index, ArrayList c) ......
//定义接口 public interface Washer { public static final int ON = 1 ; public static final int OFF = 0 ; abstract void startUp(); //启动 abstract void letWaterIn(); //进水 abstract void washClothes(); //洗衣 abstract void letWaterOut(); //排水 abstract void stop(); //停止 } //实现接口 class RoseBrand implements Washer{ public void startUp(){ System.out.println("startUp");} public void letWaterIn(){System.out.println("letWaterIn");} public void washClothes(){System.out.println("washClothes");} public void letWaterOut(){System.out.println("letWaterOut");} public void stop(){System.out.println("stop");} public void dehydrate(){System.out.println("dehydrate ");}//脱水 } //使用接口 public class Consumer { public static void main(String args[]){ //接口声明引用实现接口的RoseBrand类的对象。 Washer w = new RoseBrand(); w.startUp(); w.letWaterIn(); w.washClothes(); w.letWaterOut(); w.stop(); //w.dehydrate ();当通过接口调用玫瑰洗衣机类独有的, //接口未定义的功能方法,编译会报错。 } }
注意:
-
在类中,用implements关键字来实现接口。一个类可以实现多个接口,在implements后用逗号隔开多个接口的名字。一个接口也可被多个类来实现。
-
接口中的字段(域)的值存储在该接口的静态存储区域内,使用接口名.字段或实现类.字段均可访问。
- 如果实现某接口的类不是abstract修饰的抽象类,则在类的定义部分必须实现接口的所有抽象方法,而且方法头部分应该与接口中的定义完全一致。
- 如果实现接口的类是abstract类,则它可以不实现该接口的所有方法。但对于抽象类的任何一个非抽象的子类而言,接口中的所有抽象方法都必须实现。
-
类在实现接口的抽象方法时,必须显式使用public修饰符,否则将被警告为缩小了接口中定义的方法的访问控制范围。
6.抽象类与接口的异同点是什么?
相同点:
- 不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
- 都有自己的声明,可以引用子类或实现类对象
不同点:
- 抽象类可以有域变量,接口没有,只能是静态常量。
- 抽象类可以有具体方法;接口全是抽象方法。
- 抽象类实现靠子类继承,接口靠实现类。
7.引用比较方法有哪些?
- equals方法比较。
- 使用“==”进行比较。
- 使用instanceof比较引用类型
8.内部类的作用是什么?什么情况下使用匿名内部类?
作用:
- 内部类可以很好的实现隐藏。一般的非内部类,是不允许有 private 与protected权限的,但内部类可以。
- 内部类拥有外围类的所有元素的访问权限。
- 可是实现多重继承。
- 可以避免修改接口而实现同一个类中两种同名方法的调用。
9.不上机,判断下面程序的输岀结果。
class X { Y b = new Y(); X() { System.out.println("X"); } } class Y { Y() { System.out.println("Y"); } } public class Z extends X{ Y y = new Y(); Z() { System.out.println("Z"); } public static void main(String[] args) { new Z(); } }
A. Z B. YZ C. XYZ D. YXYZ
答案:D
解析:执行new Z();后,进入Z类,首先实现父类X,实现X时又由于Y b = new Y();先实现Y,于是输出Y,完毕后回到X,输出X,再回到Z类,执行Y y = new Y();输出Y,最后输出Z。
10.什么是数据隐藏?如何证明子类对父类同名方法进行重新定义,只能是方法的覆盖,而不是方法的隐藏?
-
在子类对父类的继承中,如果子类的成员变量和父类的成员变量同名,此时称为子类隐藏(override)了父类的成员变量。
-
覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同。
隐藏:父类和子类拥有相同名字的属性或者方法( 方法隐藏只有一种形式,就是父类和子类存在相同的静态方法)时,父类的同名的属性或者方法形式上不见了,实际是还是存在的。
11.A1、A2分别是具体类A的子类,A3为A1的子类,A1、A2之间的关系为平行类, 如图6.15所示。下面的代码为连续的程序片段,请问哪些是正确的?
A a = new A(); a = new A1(); a = new A2(); a = new A3(); A1 a1 = new A3 (); A3 a3 = a1; //× A2 a2 = new A1(); //× a3 = new A2(); //×
12.借助JDK帮助,编写程序实现这样的功能:Applet当中的TextField,每输入任一字符,在一个label当中都能动态跟踪刷新。
import java.applet.*; import java.awt.*; import java.awt.event.*; public class test extends Applet implements ActionListener{ private TextField input; private double d=0.0; //进行初始化工作,产生对象,加入监听者 public void init(){ input = new TextField(10); //myApplet是容器,input是组件,调用add使input嵌入容器 add(input); input.addActionListener(this); //向TextField注册监听器 } public void paint(Graphics g){ g.drawString("您输入了数据"+d,10,50); } public void actionPerformed(ActionEvent e) { d=Double.valueOf(input.getText()).doubleValue(); //进行刷新,调用paint()方法 repaint(); } }