Presentation is loading. Please wait.

Presentation is loading. Please wait.

JAVA程序设计 第5章 深入理解JAVA语言.

Similar presentations


Presentation on theme: "JAVA程序设计 第5章 深入理解JAVA语言."— Presentation transcript:

1 JAVA程序设计 第5章 深入理解JAVA语言

2 5.1 变量及其传递 5 .1.1 基本类型变量与引用型变量 基本类型:其值直接存于变量中。
基本类型变量与引用型变量 基本类型:其值直接存于变量中。 引用型的变量除占据一定的内存空间外,它所引用的对象实体(由new 创建)也要占据一定空间。 引用型变量保存的实际上是对象在内存的地址,也称为对象的句柄。 MyDate.class

3 引用型变量与对象实体的关系 m day n month year

4 MyDate m,n; n=new MyDate(); n=m; n.addYear();

5 5.1.2 域变量与局部变量 从语法角度看 从存储角度看 域变量属于类或接口;public,private,static,final 修饰。
域变量与局部变量 从语法角度看 域变量属于类或接口;public,private,static,final 修饰。 而局部变量是在方法中定义的变量或方法的参变量。 都可用Final修饰,而局部变量则不能够被访问控制符及static修饰。 从存储角度看 从变量在内存中的存储方式来看,域变量是对象的一部分,而对象是存在于堆中的,局部变量是存在于栈中。 域变量的生命周期与局部变量的生命周期比较。 另外,域变量可以自动赋初值,局部变量则须显式赋值。局部变量必须显示赋值后才能够使用。

6 class Test() { int a; void m(){ int b; System.out.println(b);//编译不能通过需要//初始化。 }

7 5.1.3 变量的传递 调用对象方法时,要传递参数。在传递参数时,Java 是值传递,即,在调用一个方法时,是将表达式的值复制给形式参数。
对于引用型变量,传递的值是引用值(可以理解为内存地址)。 TransByValue.java

8 Java中的参数都是按值传递的,但对于引用型变量,传递的值是引用值,所以方法中对数据的操作可以改变对象的属性。

9 public class TransByValue {
private static int a; public static void main(String[] args) { int a=0; modify(a); System.out.println(a); int[] b=new int[1]; modify(b); System.out.println(b[0]); //1 or 5 } public static void modify(int a){ a++; public static void modify(int[] b){ b[0]++; b=new int[5]; } ///:~

10 5.1.4 变量的返回 方法的返回: Object getNewObject() { Object obj=new Object();
变量的返回 方法的返回: 返回基本类型。 返回引用类型。它就可以存取对象实体。 Object getNewObject() { Object obj=new Object(); return obj; } 调用时:Object p= GetNewObject();

11 5.2 多态和虚方法调用 多态(Polymorphism)是指一个程序中相同的名字表示不同的含义的情况。
覆盖(override) (子类对父类方法) 重载(overload) (同一个类中定义多个同名的不同方法)。 动态绑定(dynamic binding) ----虚方法调用(virtual method invoking) 。 它能够使对象所编写的程序,不用做修改就可以适应于其所有的子类,如在调用方法时,程序会正确地调用子对象的方法。 多态的特点大大提高了程序的抽象程度和简洁性,更重要的是,它最大限度地降低了类和程序模块之间的耦合性,提高了类模块的封闭性,使得它们不需了解对方的具体细节,就可以很好地共同工作。这个优点对于程序的设计、开发和维护都有很大的好处。

12 5.2.1 上溯造型 就是把派生类型当作基本类型处理的过程。 doStuff(Shape s){ s.erase(); //…
s.draw(); }

13 Circle c=new Circle; Triangle t= new Triangle(); Line l= new Line(); doStuff(c); doStuff(t); doStuff(l);

14 5.2.2 虚方法调用 所有的非final方法都会自动地进行绑定! TestVirtualInvoke.java
虚方法调用 所有的非final方法都会自动地进行绑定! TestVirtualInvoke.java 用虚方法调用,可以实现运行时的多态! 在使用上溯造型的情况下,子类对象可以当做父类对象,对于重载或继承的方法,Java运行时系统根据调用该方法的实例的类型来决定选择哪个方法调用。

15 虚方法调用 子类重载了父类方法时,运行时,系统调用子类的方法。
运行时,根据实际的类型调用正确的方法,对面向对象的程序设计来说,就叫“多态型性”。 用虚方法调用,可以实现运行时的多态,它体现了面向对象程序设计中的代码复用性。已经编译好的类库可以调用新定义的子类的方法而不必重新编译,而且如果增加几个子类的定义,只需分别用new生成不同子类的实例,会自动调用不同子类的相应方法。

16 Circle c=new Circle();
Triangle t=Triangle(); Line l=new Line(); doStiff(c); doStiff(t); doStiff(l);

17

18 继承时,如果使用super.则调用父类的方法。
例 Test_Virtual_Super.java

19 static,private, 和 final不存在虚方法的调用问题。 Static的方法,以申明的类型为准,与实例类型无关
Test_Virtual_Static.java Private方法子类看不见,也不会被虚化 Final方法子类不能覆盖,不存在虚化问题

20 5.2.3 动态类型确定 1. 变量 instanceof 类型 结果是boolean 值。 InstanceOf1.java

21 2. Class类 对象可以通过getClass()方法来获得运行时的信息。
getClass()是java.lang.Object的方法,而Object是所有类的父类。所以任何对象都可以用getClass()方法。 这种获得运行时对象的方法也叫反射。 RunTimeClassInfo.java getClass()方法得到对象的运行时的类信息,即一个Class类的对象,它的getFields()及getMethods()方法能进一步获得其详细信息 注:在JDK1.5以上的版本中,还有元数据注记(Annotation)来进一步增强反射功能 )

22 5.3 对象构造与初始化 5.3.1 调用本类或父类的构造方法 this调用本类的其他构造方法。 super调用直接父类的构造方法
调用本类或父类的构造方法 this调用本类的其他构造方法。 super调用直接父类的构造方法 如果没有this及super,则编译器自动加上super(),即调用直接父类不带参数的构造方法。 this或super要放在第一条语句,且只能够有一条.

23 解决方法: 在B的构造方法中,加入super(3); 在A中加入一个不带参数的构造方法,A(){}
Class A { A(int a){} } Class B extends A B(String s){} //编译不能够通过. 编译器会自动调用B(String s){ super();} 出错. 解决方法: 在B的构造方法中,加入super(3); 在A中加入一个不带参数的构造方法,A(){} 去掉A中全部的构造方法,则编译器会自动加入一个不带参数的构造方法,称为默认的构造方法.

24 在构造函数中使用this和super. ConstructCallThisAndSuper.java

25 在构造方法中调用this及super或自动加入的super,最终保证了任何一个构造方法都要调用父类的构造方法,而父类的构造方法又会再调用其父类的构造方法,直到最顶层的Object类。这是符合面向对象的概念的,因为必须令所有父类的构造方法都得到调用,否则整个对象的构建就可能不正确。

26 5.3.2 构造方法的执行过程 对于一个复杂的对象,构造方法的执行过程遵照以下步骤: 调用本类或父类的构造方法,直至最深一层派生类。
按照声明顺序执行域的初始化赋值。 执行构造函数中的各语句。 ConstructSequence.java 构建器的调用顺序非常重要。先父类构造,再本类成员赋值,最后执行构造方法中的语句。

27

28 实例初始化与静态初始化 在类中直接写 或 { 语句…. } 实例初始化,先于{}中的语句执行 static { 语句…. }
{ 语句…. } 实例初始化,先于{}中的语句执行 static { 语句…. } 静态初始化,在第一次使用这个类时要执行,且总是先于实例的初始化,但其执行的时机是不确定的。 例:InitialTest.java

29 5.3.3构造方法内部调用的方法的多态性 在构造子类的一个对象时,子类构造方法会调用父类的构造方法,而如果父类的构造方法中调用该对象的其他方法,如果所调用的方法又被子类所覆盖的话,它可能实际上调用的是子类的方法 ,这是由动态绑定(虚方法调用)所决定的。从语法上来说这是合法的,但有时会造成事实上的不合理,所以在构造方法中调用其他方法要小心。 ConstructInvokeMetamorph.java

30

31 在本例中,在构造函数中调用了一个动态绑定的方法sayHello(),这时,会使用那个方法被覆盖的定义,而这时对象尝未完全构建好,所以School还没有赋值。
因此,可能的话,在构建器中避免调用任何方法,用尽可能简单的方法使对象进入就绪状态。 惟一能够安全调用的是具有final属性的方法。

32 5.4 对象清除与垃圾回收 new创建对象。 自动清除,清除过程称为垃圾回收。

33 5.4.1 对象的自动清除 对象回收是由 Java虚拟机的垃圾回收线程来完成的。
系统中的任何对象都有一个引用计数器,当其值为0时,说明该对象可以回收。

34 String method(){ String a,b; a=new String(“hello world”); b=new String(“game over”); System.out.println(a+b+”Ok”); a=null; a=b; return a; }

35 5.4.2 System.gc()方法 它是System类的static方法, 它可以要求系统进行垃圾回收。但它仅仅只有建议权。

36 5.4.3 finalize()方法 关闭打开的文件、清除一些非内存资源等工作需要在对象懂得回收时进行,这可以通过覆盖Object 的finalize()方法来实现。因为系统在回收时会自动调用对象的finalize() 方法。 一般来说,子类的finalize()方法中应该调用父类的finalize()方法,以保证父类的清理工作能够正常进行。 protected void finalize() throws Throwable TestCleanUp.java

37

38 本例中,每个类都有一个方法cleanup()来负责清理工作。先完成本类的有关工作,然后调用父类的清除方法。
finally表明:无论会发生什么事情,总是为X调用cleanup().

39 JDK7中的try-with-resources
对于实现了java.lang.AutoCloseable的对象 try( Scanner scanner= new Scanner( … ) ){ } 会自动调用其close()方法

40 5.5 内部类与匿名类 内部类是在其他类中的类。 匿名类是一种特殊的内部类,它没有类名,在定义类的同时就生成该对象的一个实例。
1.内部类的定义和使用 将类的定义置入一个用于封装它的类内部即可。 内部类不能够与外部类同名。 在封装它的类的内部使用内部类,与普通类的使用方式相同,在其他地方使用,类名前要冠以外部类的名字。在用new创建内部类时,也要在 new前面冠以对象变量。 InnerUse.java

41

42 2. 在内部类中使用外部类的成员 内部类中可以直接访问外部类的其他域及方法。即使private也行。
如内部类中有与外部类同名的域或方法,可以用this来访问外部成员。 TestInnerThis.java

43 3.内部类的修饰符 内部类与类中的域、方法一样是外部类的成员,它的前面也可以有访问控制符和其他修饰符。内部类可用的修饰符比外部类的修饰符更多。(外部类不能够使用protected,private,static等修饰,而内部类可以。 访问控制符:public,protected,默认及private。 Final,abstract。 用static修饰表明该内部类实际是一种外部类。

44 Static 环境在使用时要遵循以下规则:
1、实例化static内部类时,在 new前面不需要用对象变量; 2、Static内部类中不能访问其外部类的非static的域及方法,既只能够访问static成员。 3、static方法中不能访问非static的域及方法,也不能够不带前缀地new 一个非static的内部类。

45 TestInnerStatic.java

46 5.5.2 方法中的内部类及匿名类 1。方法中的内部类 在一个方法中也可以定义类。这种类称为方法中的 内部类。
TestInnerMethod.class

47

48 1、同局部变量一样,方法中的内部类前不能够用 public,private,protected,static修饰,但可以被final或者abstract修饰。
2、方法中的内部类可以访问其外部类的成员;若是Static中的内部类可以访问外部类的static成员。 3、方法中的内部类中,不能够访问该方法的局部变量,除非是final局部变量。 4、方法中定义的类,在其他地方使用时,没有类的情况,正像例中一样,只能够用其父类来引用这样的变量。

49 2。匿名类 匿名类有以下几个特点: 1、不取名字,直接用其父类的名字。
2、类的定义域创建该类的一个实例同时进行,即类的定义前面有一个new。不使用关键词class。 new 类名或接口名(){……}。 3、类名前面不能够有修饰符。 4、类中不能够定义构造方法,因为它没有名字。在构造对象时不能够带参数。

50 TestInnerAnonymous.java

51

52 5.6 装箱、拆箱、枚举 从JDK1.5之后,增加了对基本类型的使用的一些改进 Complier sugar

53 基本类型的包装类 int  Interger 类似的还有Boolean, Byte, Short, Character,
Integer, Long, Float, Double Integer I = new Integer(10);

54 自动装箱与拆箱 Boxing Unboxing Integer I = 10; int i = I; 实际译为
Integer I= Integer.valueOf(10); int i = I.intValue(); 主要方便用于集合中,如: Object [] ary = { 1, "aaa"}; System.out.println(String.format("%s %s", ary));

55 思考 Integer i = new Integer(10); Integer j = new Integer(10);
System.out.println(i==j); Integer m = 10; Integer n = 10; System.out.println(m==n); Integer p = 200; Integer q = 200; System.out.println(p==q);

56 枚举enum public enum Action{ public enum Prority{ MAX, NORM, MIN; }
STOP, RIGHT, LEFT, UP, DOWN} public enum Prority{ MAX, NORM, MIN; } 多用于switch Prority p = Prority.MAX; switch(p){ case MAX: System.out.println("ok");break; case 后只跟MAX,不跟类名


Download ppt "JAVA程序设计 第5章 深入理解JAVA语言."

Similar presentations


Ads by Google