1、Java 高级类特性,讲师:佟刚 新浪微博:尚硅谷-佟刚,尚硅谷:http:/ 关键字 final 关键字 抽象类(abstract 关键字) 接口(interface 关键字) 内部类,本章内容,static 关键字 静态属性 静态初始化 静态方法 单子模式 理解main方法的语法 final 关键字 抽象类(abstract 关键字) 接口(interface 关键字) 内部类,当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用。我们有时候希望无论是否产生了对象或无论产生
2、了多少对象的情况下,某些特定的数据在内存空间里只有一份,例如所有的中国人都有个国家名称,每一个中国人都共享这个国家名称,不必在每一个中国人的实例对象中都单独分配一个用于代表国家名称的变量。,关键字 static,关键字 static,class Circleprivate double radius;public Circle(double radius)this.radius=radius;public double findArea()return Math.PI*radius*radius; 创建两个Circle对象 Circle c1=new Circle(2.0); /c1.radi
3、us=2.0 Circle c2=new Circle(3.0); /c2.radius=3.0 Circle类中的变量radius是一个实例变量(instance variable),它属于类的每一个对象,不能被同一个类的不同对象所共享。 上例中c1的radius独立于c2的radius,存储在不同的空间。c1中的radius变化不会影响c2的radius,反之亦然。,如果想让一个类的所有实例共享数据,请用类变量,关键字 static,在Java类中声明变量、方法和内部类时,可使用关键字static做为修饰符。 static标记的变量或方法由整个类(所有实例)共享,如访问控制权限允许,可不必
4、创建该类对象而直接用类名加.调用。 static成员也称类成员或静态成员,如:类变量、类方法、静态方法等。,类变量(class Variable),类变量(类属性)由该类的所有实例共享,public class Person private int id;public static int total = 0;public Person() total+;id = total;,Person p1=new Person();,Person p2=new Person();,类属性类似于全局变量,类属性应用举例,class Person private int id;public static
5、int total = 0;public Person() total+;id = total;public static void main(String args)Person Tom=new Person()Tom.id=0;total=100; / 不用创建对象就可以访问静态成员public class OtherClass public static void main(String args) Person.total = 100; / 不用创建对象就可以访问静态成员/访问方式:类名.类属性类名.类方法System.out.println(Person.total);Person
6、c = new Person(); System.out.println(c.total); /输出101 ,class Person private int id;private static int total = 0;public static int getTotalPerson() return total;public Person() total+;id = total; public class TestPerson public static void main(String args) System.out.println(“Number of total is “ +Pe
7、rson.getTotalPerson();/没有创建对象也可以访问静态方法Person p1 = new Person();System.out.println( “Number of total is “+ Person.getTotalPerson(); ,类方法(class Method),没有对象的实例时,可以用类名.方法名()的形式访问由static标记的类方法。,The output is: Number of total is 0 Number of total is 1,类方法,在static方法内部只能访问类的static属性,不能访问类的非static属性。,class
8、Person private int id;private static int total = 0;public static int getTotalPerson() id+; /非法return total;public Person() total+;id = total; ,类方法,因为不需要实例就可以访问static方法,因此static方法内部不能有this,(也不能有super ? ),class Person private int id;private static int total = 0;public static void setTotalPerson(int to
9、tal)this.total=total; /非法,在static方法中不能有this,也不能有superpublic Person() total+;id = total; public class TestPerson public static void main(String args) Person.setTotalPerson(); ,类方法(class Method),在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象。静态方法不能以
10、任何方式引用this和super关键字。与上面的道理一样,因为静态方法在使用前不用创建任何实例对象,当静态方法被调用时,this所引用的对象根本就没有产生。main() 方法是静态的,因此JVM在执行main方法时不创建main方法所在的类的实例对象,因而在main()方法中,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员,这种情况,我们在以后的例子中会多次碰到。,类属性、类方法的设计思想,类属性作为该类各个对象之间共享的变量。在设计类时,分析哪些类属性不因对象的不同而改变,将这些属性设置为类属性。相应的方法设置为类方法。如果方法与调用
11、者无关,则这样的方法通常被声明为类方法,由于不需要创建对象就可以调用类方法,从而简化了方法的调用练习1:编写一个类,实现银行账户的概念,包含的属性有“帐号”、“密码”、“存款余额”、“利率”、“最小余额”,定义封装这些 属性的方法。账号要自动生成。 编写主类,使用银行账户类,输入、输出3个储户的上述信息。 考虑:哪些属性可以设计成static属性。 Bank.java,静态初始化,一个类中可以使用不包含在任何方法体中的静态代码块(static block ),当类被载入时,静态代码块被执行,且只被执行一次,静态块经常用来进行类属性的初始化。 static块通常用于初始化static (类)属性
12、 class Person public static int total;static total = 100;/为total赋初值 /其它属性或方法声明,静态初始化举例,class Person public static int total;static total = 100;System.out.println(“in static block!“); public class Test public static void main(String args) System.out.println(“total = “+ Person.total);System.out.printl
13、n(“total = “+ Person.total); ,输出: in static block total=100 total=100,设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就想是经典的棋谱,不同的棋局,我们用不同的棋谱,免得我们自己再去思考和摸索。 所谓类的单态设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将类的构造方法的访问权限设置为private,这样,就不能用new 操作符在类的外部产生类的
14、对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的。,单子 Singleton 设计模板,单子Singleton 设计模板,class Singleprivate static Single onlyone = new Single();/私有的,只能在类的内部访问private String name;public static Single getSingle() /getSingle()为static,不用创建对象 /即可
15、访问return onlyone;private Single() /private的构造器,不能在类的外部创建该类的对象public class TestSinglepublic static void main(String args) Single s1 = Single.getSingle(); /访问静态方法Single s2 = Single.getSingle();if (s1=s2)System.out.println(“s1 is equals to s2!“); ,理解main方法的语法,由于java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public
16、,又因为java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数。,命令行参数用法举例,public class CommandPara public static void main(String args) for ( int i = 0; i args.length; i+ ) System.out.println(“args“ + i + “ = “ + argsi);/运行程序CommandPara.java java CommandPara lisa “bily
17、“ “Mr Brown“ /输出结果:args0 = lisa args1 = bily args2 = Mr Brown,本章内容,static 关键字 final 关键字 抽象类(abstract 关键字) 接口(interface 关键字) 内部类,关键字 final,在Java中声明类、属性和方法时,可使用关键字final来修饰。 final标记的变量(成员变量或局部变量)即成为常量,只能赋值一次。 final标记的类不能被继承。提高安全性,提高程序的可读性。 final标记的方法不能被子类重写。增加安全性。 final标记的成员变量必须在声明的同时或在每个构造方法中显式赋值,然后才能
18、使用。final PI=3.14;,关键字final应用举例,public final class Testpublic static int totalNumber= 5 ;public final int id;public Test()id = +totalNumber;/只能在构造方法中给final变量赋值public static void main(String args) Test t = new Test();System.out.println(t.id); final int i = 10;final int j;j = 20;j = 30; /非法 ,本章内容,stati
19、c 关键字 final 关键字 抽象类(abstract 关键字) 抽象类 抽象方法 接口(interface 关键字) 内部类,抽象类(abstract class),随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。 用abstract关键字来修饰一个类时,这个类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法。 抽象方法:只有方法的声明,没有方法的实现。以分号结束。abstract int abstractMethod1( int
20、a ); 含有抽象方法的类必须被声明为抽象类。 抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。 不能用abstract修饰私有方法,构造方法,静态方法。,抽象类举例,abstract class A abstract void m1( );public void m2( )System.out.println(“A类中定义的m2方法“); class B extends Avoid m1( )System.out.println(“B类中定义的m1方法“); public class Testpublic static void main( Str
21、ing args )A c = new B( );c.m1( );c.m2( ); ,抽象类应用,在航运公司系统中,Vehicle类需要定义两个方法分别计算运输工具的燃料效率和行驶距离。,抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。,问题:卡车(Truck)和驳船(RiverBarge)的燃料效率和行驶距离的计算方法完全不同。Vehicle类不能提供计算方法,但子类可以。,解决方案Java允许类设计者指定:超类声明一个方法但不提供实现,该方法的实现由子类提供。这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类。 Vehicle是一个抽象类,有两个抽象
22、方法。 public abstract class Vehiclepublic abstract double calcFuelEfficiency(); /计算燃料效率的抽象方法public abstract double calcTripDistance(); /计算行驶距离的抽象方法 public class Truck extends Vehiclepublic double calcFuelEfficiency( ) /写出计算卡车的燃料效率的具体方法 public double calcTripDistance( ) /写出计算卡车行驶距离的具体方法 public class Ri
23、verBarge extends Vehiclepublic double calcFuelEfficiency( ) /写出计算驳船的燃料效率的具体方法 public double calcTripDistance( ) /写出计算驳船行驶距离的具体方法 ,抽象类应用,注意:抽象类不能实例化 new Vihicle()是非法的,本章内容,static 关键字 final 关键字 抽象类(abstract 关键字) 接口(interface 关键字) 内部类,接 口(1),有时必须从几个类中派生出一个子类,继承它们所有的属性和方法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效
24、果。 接口(interface)是抽象方法和常量值的定义的集合。 从本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。 接口定义举例 public interface Runner int id = 1;public void start();public void run();public void stop(); ,接 口(2),接口的特点: 用 interface 来定义。 接口中的所有成员变量都默认是由public static final修饰的。 接口中的所有方法都默认是由public abstract修饰的。接口没有构造方法。 实现接口的
25、类中必须提供接口中所有方法的具体实现内容。 多个无关的类可以实现同一个接口一个类可以实现多个无关的接口与继承关系类似,接口与实现类之间存在多态性 接口也可以继承另一个接口,使用extends关键字。,接 口(3),实现接口的类中必须提供接口中所有方法的具体实现内容。 多个无关的类可以实现同一个接口一个类可以实现多个无关的接口与继承关系类似,接口与实现类之间存在多态性定义Java类的语法格式:class extends implements ,* *,接口应用举例(1),public interface Runner public void start();public void run();p
26、ublic void stop(); public class Person implements Runner public void start() / 准备工作:弯腰、蹬腿、咬牙、瞪眼 / 开跑public void run() / 摆动手臂/ 维持直线方向public void stop() / 减速直至停止、喝水。 ,接口应用举例(2),接口应用举例(3),一个类可以实现多个无关的接口 interface Runner public void run(); interface Swimmer public double swim(); class Animal public int
27、eat() class Person extends Animal implements Runner,Swimmerpublic void run() public double swim() public int eat() 与继承关系类似,接口与实现类之间存在多态性 public class Testpublic static void main(String args)Test t = new Test();Person p = new Person();t.m1(p);t.m2(p);t.m3(p);public String m1(Runner f) f.run(); public
28、 void m2(Swimmer s) s.swim();public void m3(Animal a) a.eat(); ,接口的其他问题,如果实现接口的类中没有实现接口中的全部方法,必须将此类定义为抽象类。 接口也可以继承另一个接口,使用extends关键字。 interface MyInterfaceString s=“MyInterface”;public void absM1();interface SubInterface extends MyInterfacepublic void absM2();public class SubAdapter implements SubIn
29、terfacepublic void absM1()System.out.println(“absM1”);public void absM2()System.out.println(“absM2”);实现类SubAdapter必须给出接口SubInterface以及父接口MyInterface中所有方法的实现。,练习2,定义一个接口用来实现两个对象的比较。 interface CompareObject public int compareTo(Object o); /若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小 定义一个Circle类。 定义一个Compar
30、ableCircle类,继承Circle类并且实现CompareObject接口。在ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。 定义一个测试类TestInterface,创建两个ComaparableCircle对象,调用compareTo方法比较两个类的半径大小。 思考:参照上述做法定义矩形类Rectangle和ComparableRectangle类,在ComparableRectangle类中给出compareTo方法的实现,比较两个矩形的面积大小。,本章内容,static 关键字 final 关键字 抽象类(abstract
31、 关键字) 接口(interface 关键字) 内部类,内部类,在Java中,允许一个类的定义位于另一个类的内部,前者称为内部类 内部类和外层封装它的类之间存在逻辑上的所属关系 Inner class一般用在定义它的类或语句块之内,在外部引用它时必须给出完整的名称。 Inner class的名字不能与包含它的类名相同; Inner class可以使用包含它的类的静态和实例成员变量,也可以使用它所在方法的局部变量;,内部类举例 (1),class A private int s;public class Bpublic void mb() s = 100; System.out.println(
32、“在内部类B中s=“ + s);public void ma() B i = new B();i.mb();public class Test public static void main(String args)A o = new A();o.ma();,内部类举例 (2),public class Aprivate int s = 111;public class B private int s = 222;public void mb(int s) System.out.println(s); / 局部变量sSystem.out.println(this.s); / 内部类对象的属性s
33、System.out.println(A.this.s); / 外层类对象属性spublic static void main(String args)A a = new A();A.B b = a.new B();b.mb(333); ,内部类特性,Inner class可以声明为抽象类 ,因此可以被其它的内部类继承。也可以声明为final的。 和外层类不同,Inner class可以声明为private或protected; Inner class 可以声明为static的,但此时就不能再使用外层封装类的非static的成员变量; 非static的内部类中的成员不能声明为static的,只有在顶层类或static的内部类中才可声明static成员;,