260 likes | 433 Views
非访问控制符( static,final,abstract ). Static: 静态的,多个实例中的这个成员不被额外分配空间,都指向这个静态成员的引用。都是对同一个内存单元的访问或操作 。 注意: 1、该类的任何一个对象访问该静态成员变量时,得到同一个值。 2、跟踪创建的实例数 3、类似于全局变量 4、非 private 的静态成员变量无需创建实例就可以从类的外部访问。. public class StaticExample{ static int globalCount = 0;
E N D
非访问控制符(static,final,abstract) • Static:静态的,多个实例中的这个成员不被额外分配空间,都指向这个静态成员的引用。都是对同一个内存单元的访问或操作。 • 注意: • 1、该类的任何一个对象访问该静态成员变量时,得到同一个值。 • 2、跟踪创建的实例数 • 3、类似于全局变量 • 4、非private的静态成员变量无需创建实例就可以从类的外部访问。
public class StaticExample{ • static int globalCount = 0; • public static void main( String[] args) • { • StaticExample example1 = new StaticExample(); • StaticExample example2 = new StaticExample(); • example1.globalCount ++ ; • example2.globalCount ++ ; • System.out.println("globalCount of example1 = " + example1.globalCount); • System.out.println("globalCount of example2= " + example2.globalCount); • System.out.println("globalCount = " + StaticExample.globalCount); • } • }
class count{ private int serial; private static int counter=0; count(){ counter++; serial=counter; } int getserial(){ return serial; } } class StaticVar{ static int x=100; } public class statictest{ public static void main(String[] args){ count1 c1=new count(); count2 c2=new count(); System.out.println(c1.getserial()); System.out.println(c2.getserial()); System.out.println(staticvar.x++); System.out.println(staticvar.x++); } } Static的使用
final • final用来修饰一个不可再次更改的定义。 • 修饰类,此类不能有子类,不能被继承,修饰一个方法,此方法不能在子类中被覆盖,修饰一个变量,只能也必须被赋值一次(常量)。
class FinalExample{ • static final int i; • static final int j; • public static final int TOTAL = 10; • public FinalExample(int i) • { • this.i = i ; • } • public static void main(String[] args) • { • FinalExample example = new FinalExample(1); • example.i = 10; • example.j = 1; • } • }
abstract • 可以用来修饰类或方法,抽象类:方法定义可以没有方法主体,只有方法声明;被abstract修饰的方法在非抽象的子类中必须有具体的实现
接口 • 用来定义一些抽象方法和域的定义 • 不包含方法的任何实现,都是抽象方法 • 接口定义的方法和域具备public访问权限 • 接口不能直接用来创建对象,因此不包含构造方法的定义 • 只是定义某组操作的使用规范,不关心具体的实现。 • public interface 接口名[extends父接口名列表] • { public static final 域类型 域名=常量值 • public abstract 返回值类型 方法名(参数列表); • }
接口的实现 • Public interface drivecontrol{ • void startengine(); • } • public class car implements drivecontrol{ • String model; • public car(){} • public car(String model){ • this.model=model; • } • void printmodel(){ • System.out.println(“this model of car is ”+this.model); • } • public void startengine(){ • System.out.println(“start engine”); • }
接口注意事项 • 用implements声明 • 可实现多个接口,用逗号隔开 • 一个非抽象类实现接口时,必须全部方法的实现,若不需要也要空实现,抽象类可实现部分方法。 • 接口进行实现,必须显式使用public
包(package) • 包是若干类的集合,表现为具体的文件夹或如jar压缩文件 • 每个类在编译时被指定属于一个特定的包,用package说明 • 若未指定,所有类被组合到一个缺省包中,不能被其它包中的类引用。 • package语句必须作为java代码的第一条语句使用,且必须是非注释非空行的第一行 • 若引用另一个包中的定义的类时,用import
package mypk; public class A { public void print(String s) { B bl = new B(); System.println( bl.addString(s)); } } class B { String addString(String s) { return " ----- " + s + " ---- -"; } } import mypk. * ;public class Test { public static void main(String[] args) { A al = new A(); al.print("test"); } }
继承 为一个已有的类的属性或操作进行扩展或修正,父类,子类(派生类)一子只能有一个直接父类。 子类可直接继承父类非私有属性和方法外,还可以修改父类的属性或者重载父类中定义的操作,以及添加新的属性和方法 形式: 子类名 extends 父类名{ }
import java.io.*; abstract class cleanser{ private String s=new String(“cleanser”); public void append(String a){ s+=a; } public void dilute(){ append(“dilute()”); } public void apply(){ append(“apply()”); } public abstract void scrub(); public void print(){ System.out.println(s); } } public class detergent extends cleaner{ public void scrub(){ append(“detergent.scrub()”); } public void foam(){ append(“foam()”); } public static void main(String[] args){ detergent x=new detergent(); System.out.println(“test subclass”); x.dilute();x.apply(); x.scrub();x.foam(); x.print(); detergent x1=new detergent(); cleanser x2=x1; System.out.println(“testing ”); x2.dilute();x2.apply(); x2.scrub();x2.print(); } }
域的隐藏:如果子类中定义一个与从父类那里继承来的成员变量完全相同的变量域的隐藏:如果子类中定义一个与从父类那里继承来的成员变量完全相同的变量 访问方法: 调用从父类继承的方法操作 使用super.变量名 方法的覆盖:定义一个与父类中方法同名的方法 注意 完全相同的方法名 完全相同的参数列表 完全相同类型的返回值 隐藏和覆盖
隐藏和覆盖 • 区别: • 子类隐藏父类的变量只是使得在子类中不可见,父类的同名变量在子类对象中仍然占有自己的独立的内存空间 • 子类方法的覆盖将清除父类方法在子类中占用的内存,从而使得父类方法在子类对象中不存在
class test{ public static void main(String[] args) a a1=new a(); a1.print() b b1=new b(); b1.print(); } class a{ int x=1; void print(){ System.out.println(x) } } Class b extends a { Int x=100; Void print(){ System.out.println(“super.x=”+super.x); Super.print(); System.out.println(“x=”+x); } } 方法的覆盖:案例3.7(上机测试)
构造方法的重载和继承 • 类中与类名同名的方法称为类的构造方法,在创建每个新的类对象时自动执行,以保证新对象的各成员有合法确定的值 • 构造方法没有返回类型 • 构造方法只能在创建类对象时由系统隐含调用,不能直接引用 • 类名 对象名=new 构造方法(); • 当类中没有构造方法时,系统隐含配一个构造方法,空的 • 一个类中可以有多个构造方法,同个类中可以有多个同名的不同方法,称为java的重载,当同一个方法调用同类中方法时用this ,父类中用super
class meal{ meal(){ System.out. println(“meal()”);}} class bread{ bread(){ System.out. println(“bread()”);}} class cheese{ cheese(){ System.out. println(“cheese()”);}} class lunch extends meal{ lunch (){ System.out. println(“lunch() ”);}} class portablelunch extends lunch{ portablelunch(){ System.out.println (“portablelunch() ”);}} class sandwich extends portablelunch { bread b=new bread(); cheese c=new cheese(); sandwich(){ System.out. println(“sandwich() ”);} public static void main(String[] args){ new sandwich();} } 构造方法的继承
构造方法注意事项 • 如果是有参数的构造方法不会自动继承,在子类中对这个构造方法进行覆盖,必须显示的加入对父类构造方法的覆盖定义。如果定义一个包含参数的构造方法,加入无参数的构造方法的定义。
public class test{ public static void main(String args[]) { a a1 = new a(); System.out.println(a1.x); a a2 = new a(5); System.out.println(a2.x); sa sa1 = new sa(); System.out.println(sa1.x); sb sb1 =new sb(); System.out.println(sb1.x); sb sb2 = new sb(5); System.out.println(sb2.x); sb sb3 = new sb(5,100); System.out.println(sb3.x); ssb ssb1 = new ssb(); System.out.println(ssb1.x); } } class a{ int x = 1; a(){x = 10;} a(int p1) {x = x + p1;} } class sa extends a {} class sb extends a { sb(){x = x +3;} sb(int p1){x = x +p1;} sb(int p1, int p2) { super(p1); x = x +p2; } } class ssb extends sb{ ssb() {x = x + 6;} }
this和super • this是指向当前对象的一个引用型变量,表示的是当前对象本身 • this 只能在方法中使用,表示当前类的对象或类的当前实例,有时用于: • Birthday bd=new Birthday(this); • super 指向父类对象的一个引用型变量,表示的是当前对象的直接父类对象。 • 用super(..)调用父类构造方法时,必须是子类构造方法的第一条可执行语句。
class Leaf{ • private int i = 0; • Leaf increment() • { i++; • return this; } • void print() • { System.out.println("i =" + i); } • } • public class a{ • public static void main(String[] args) • { • Leaf x = new Leaf(); • x.increment().increment().increment().print(); • } • }
public class SaloonCar extends Car{ • private double price; • public SaloonCar(String model) • { super(model); • this.price = 1; } • void printModel(){ • System.out.println("The model of this saloon car is " +super.model); } • void printPrice(){ • System.out.println("The price is " +price + "m dollar"); } • public static void main(String[] args){ • SalooonCar saloonCar = new SaloonCar("saloon car midel"); • saloonCar.printModel(); • saloonCar.printModel(); • } • }
组合与多态 • 在新类里简章创建原有类的对象,称为组合。 • 在程序中使用相同的名称来表示不同的含义 • 运行期方法调用绑定:在对子类对象使用时,可以将子类对象当作父类对象使用。Car car =new salooncar(); • 同名的不同方法在不同的类中,调用时指明是哪个类的方法
class shape{ void draw(){} void erase(){} } class circle extends shape{ void draw(){ System.out.println(“circle.draw()”);} void erase(){ System.out.println(“circle.erase()”);} } Class square extends shape{ void draw(){ System.out.println(“square.draw()”);} void erase(){ System.out.println(“square.erase()”);} } class triangle extends shape{ void draw(){ System.out.println(“triangle .draw()”);} void erase(){ System.out.println(“triangle .erase()”);} } public class shapes{ public static shape randshape(){ switch((int)(Math.random()*3)){ case0:return new circle(); case1:return new square(); case2:return new triangle(); default:return null;}} public static void main(String[] args){ shape[] s=new shape[9]; for(int I=0;I<s.length;I++) s[I]=randshape(); for(int I=0;I<s.length;I++) s[I.draw();}}
注意构造方法与多态:显式的说明调用的是父类还是子类的方法注意构造方法与多态:显式的说明调用的是父类还是子类的方法 • 上机测试3.10.3 • 案例分析(如何分析定义一个完整题目) • 习题:1-8掌握,9-15上机测试