370 likes | 516 Views
第 4 讲:面向对象特征( 2 ). 1 对象与引用 2 类. 1 对象与引用. 1.1 引用的本质 在 Java 中引用是指向一个对象在内存中的位置 , 在本质上是一种带有很强的完整性和安全性的限制的指针,当你声明某个类 , 接口或数组类型的一个变量时 , 那个变量的值总是某个对象的引用或者是 null 引用 1.2 与指针的区别 指针就是简单的地址而已 , 引用除了表示地址而外 , 还象被引用的数据对象的缩影 , 还提供其他信息 . 指针可以有 ++,-- 运算 , 引用不可以运算. 0. 0. 0.
E N D
第4讲:面向对象特征(2) • 1 对象与引用 • 2 类
1 对象与引用 1.1引用的本质 在Java中引用是指向一个对象在内存中的位置,在本质上是一种带有很强的完整性和安全性的限制的指针,当你声明某个类,接口或数组类型的一个变量时,那个变量的值总是某个对象的引用或者是null引用 1.2与指针的区别 指针就是简单的地址而已,引用除了表示地址而外,还象被引用的数据对象的缩影,还提供其他信息.指针可以有++,--运算,引用不可以运算
0 0 0 例: String s1;String s2; s1 a string 10001 s1=“a string”; s2 10001 s2=s1; class Mydate { int year; int month; int day; } today 10008 Mydate today=new MyDate()
1.1对象的特征 • 能够动态取得的内存有两种,一种是对象实体,一种数组. • 用new申请内存,不需要自己释放不用的内存. • 在Java中,定义数组时不必给出数组的大小,因为Java的数组是动态分配的。 • 数组变量实际上是一个引用变量,因此要实例化才能使用。 • 例:int Array[]; Array=new int[8];
例:String arrayOfString[]=new String[10]; 每个数组元素包含一个对字符串对象的引用,此时值分配了包含字符串引用的空间,并没有对字符串本身分配内存,此时不能访问。 arrayOfString[0] arrayOfString[1] arrayOfString[8] arrayOfString[9] 对 字 符 串 的 引 用 arrayOfString 对数组的引用 for(int i=0;i<arrayString.length;i++) arrayOfString[i]=new String(“Hello”+i)
System.out.println 接受的是String类 有两个字符串str1,str2 str1=str2; 是指两个引用指向同一个地址 str1.equals(str2)是指两个字符串内容相等 获取String对象的信息 String s=“this is a string”; int len=s.length(); boolean result=s.equal(“this is a test”); char ch=s.charAt(6); StringBuffer的字符串的内容是可以改变的 创建StringBuffer对象 StringBuffer str=new Stringbuffer(“hello”); 获取StringBuffer对象的信息 int len=str.length(); 例:StringBuffer sb=new StringBuffer(“Drink Java!”); sb.insert(6,”Hot ”); System.out.println(sb.toString()); Drink Hot Java!
1.2对象引用与对象实例 • public class xx { • public static void main(String[] args) • { String s1 = "You are hired!"; • String s2 = "You are hired!"; • s1 = s1.replace('h','f'); • System.out.println(s1); • if (s1==s2) { • System.out.println(“一个内存空间”);} • else { System.out.println("不是一个内存空间"); • } • } • }
2.1类的定义 • 在Java中所有的类都扩展一个超类(Object) • 在源文件中,可以定义多个类,但每次只能定义一个公共类。 • 每个类编译后都单独产生一个class文件。 • 一般类都有名字
2.1类定义 • 试用一个简单的类 class CarDemo { public static void main(String args[]) { Car Democar=new Car(); DemoCar.set_number(3838); DemoCar.show_number(); }} class Car { int car_number; void set_number(int car_num) { car_number=car_num;} void show_number() { System.out.println (“My car No. is :”+car_number); } } My car number is 3838
class TrashCar extends Car { int capacity; void set_capacity(int trash_car_capacity) { capacity=trash_car_capacity;} void show_capacity(); { System.out.println(“My capacity is: ”+ capacity);}} 类的单继承 关系 class Car { int car_number; void set_number(int car_num) { car_number=car_num;} void show_number() {System.out.println (“My car No. is :”+car_number); } }
2.1 类定义 class CarDemo { public static void main(String args[]) { TrashCar DemoTrashCar=new TrashCar(); DemoTrashCar.set_number(4949); DemoTrashCar.set_capacity(20); DemoTrashCar.show_number(); DemoTrashCar.show_capacity(); } } • TrashCar中继承了Car中的两个方法 Car是父类, TrashCar是子类
2.1 类定义 • 何时选择继承性? IS A 关系 “B是一个A吗?” 如果是则让B做A的子类. 常犯的错误A有一个B吗? 例如让汽车轮子成为汽车的子类是错误的
2.1 类定义 [类的修饰字] class 类名称 [extends 父类名称][implements 接口列表] { …. } friendly(缺省)类只能被本包中的其它类使用 1.public 无论它所处在的包定义在哪,该类都是可访问的 2.static static的内部类是一个顶级类,它和包含类的成员是不相关的。 3.final 被定义成final的类不允许出现子类 4.abstract 类中包括没有实现的方法,不能被实例化。 5.strictfp 所有浮点计算遵守 IEEE 754标准
2.2类成员定义 • 类中可以定义的部分包括属性、方法。 • 每个类都创造了有自己的名字空间,其中方法和变量可以知道彼此的存在,可以使用。 • 类中也可以定义类(内部类),静态初始化块。
2.2类成员定义 • 变量和方法的修饰字public、protected、private、static、final、transient、volatile • friendly(前边没有修饰字的情况) 在同一程序包中出现的类才可以直接使用它的数据和方法. • public: 任何其它类、对象只要可以看到这个类的话,那么它就可以存取变量的数据,或使用方法。 class ABC { public int pub_i=5; public void show)() { System.out.println(“pub_i”+pub_i); }
2.2类成员定义 class Demo { public static void main(String args[]) { ABC abc=new ABC(); System.out.println(“abc.pub_i”+abc.pub_i); abc.pub_i=10; abc.show(); } } abc.pub_i=5 pub_i=10;
2.2类成员定义 • protected变量和方法 • 如果一个类中变量或方法有修饰字protected,同一类,同一包可以使用。不同包的类要使用,必须是该类的子类可以存取变量或调用 public class ABC { protected int pro_i=5; protected void show() { System.out.println(“pro_i=” +pro_i); } }
2.2类成员定义 • 不同包中的类不能使用 class DEF { public static void main(String args[]) { ABC abc=new ABC(); System.out.println (“abc.pro_i=“+abc.pro_i); abc.pub_i=10; abc.show(); } }
2.2类成员定义 import mytest.pack.ABC; class DEF extends ABC { public static void main(String agrs[]) { DEF def=new DEF(); System.out.println(def.i); def.i=10; def.show(); } } • 不同包但是是子类 pro_i=5 pro_i=10
2.2 类成员定义 private 不允许任何其他类存取和调用 volatile因为异步线程可以访问字段,所以有些优化操作是一定不能作用在属性 transient 属性不是对象持久状态的一部分,不应该把字段和对象一起进行持久化操作。
2.2类成员定义 class demo { public static void main(String args[]) { C c=new C(); c.println_out(); }} • 当子类中的变量名与父类的相同,原来的变量被遮盖. class A { int data_a=3;} class B extends A { int data_a=5;} class C extends B { void print_out() { System.out.println(“data_a= ”+data_a); System.out.println(“A.data_a= ”+A.data_a); System.out.println(“B.data_a= ”+B.data_a); }} data_a=5 A.data_a=3 B.data_a=5
2.2类成员定义 • 方法的覆盖(overriding)和重载(overloading) • 子孙类中定义的方法和祖先类中某个方法同名,同参数行,则祖先类中的该方法被覆盖. • 方法的重载是指一个对象的多态性,即多个方法用相同的名称,但参数行不同. 123 void show(int int_num) 1.23 类 void show(double double_num) 123,1.23 void show(nit nit_ um, float float_um)
object b char data static int share_data object b char data object c char data Object b char data 2.2类成员定义 • 到此为止-----final • final在方法之前,防止该方法被覆盖. • final在变量之前,定义一个常量. • 属于类的变量和方法----static • static 在变量或方法之前, 表明它们是属于类的, class ABCD { char data; static int_share_data; } class Demo { ABCD a,b,c,d}
2.2类成员定义 • 静态变量在各实例间共享 • 如果是public静态变量,则其它类可以不通过实例化访问它们 • 静态方法称为类的方法,因此不用实例化即可调用(面向过程) • 一个对象的方法可以访问对象的数据成员,尽管不属于方法的局部变量
2.2类成员定义 • 例:不正确的引用 • class StaticError • { String mystring=“hello”; • public static void main(String args[]) • { System.out.println(mystring);} • } • 错误信息:can’t make a static reference to nonstatic variable. • 为什么不正确? 只有对象的方法可以访问对象的变量.
2.2类成员定义 • 解决的办法: • 1. 将变量改称类变量 • class StaticError • { static String mystring=“hello”; • public static void main(String args[]) • { System.out.println(mystring);} • }
2.2类成员定义 • 2. 先创建一个类的实例 class NoStaticError { public static void main(String args[]) { String mystring=“hello”; System.out.println(mystring);} } }
2.3 构造器 class Demo1 //数组的配置 { public static void main(String args[]) { int array[][]; array=new int[5][5]; array[1][4]=5; } } • 使用new来做内存配置 class myClass //对象实体的产生 { int data=5;} class Demo2 { public static void main(String args[]) { myClass obj;//建立一个引用 obj=new myClass(); System.out.println(obj.data); }}
2.3构造器 • Constructor和finalizer • constructor(构造函数),在一个类中和类同名的方法叫构造函数.系统在产生对象时会自动执行. class UsePoint { Point point_A=new Point(); Point point_B=new Point(5,7); } class Point { int x,y; Point() { x =0;y=0;} Point(int new_x,int new_y) { x=new_x,y=new_y;} }
2.3 构造器 • 构造函数应包含哪些内容? 构造函数多半定义一些初值或内存配置工作 • 一个类可以有多个构造函数(重载),根据参数的不同决定执行哪一个. • 如果程序中没有定义构造函数,则创造实例时使用的是缺省函数,它是一个无内容的空函数.
2.3 构造函数 • this • this指自己这个对象 • this的作用是要将自己这个对象当作参数,传送给别的对象中的方法. class Circle { int r; Circle(int r) {this.r=r;} public area() { return r*r*3;} } class ThisClass { public static void main() { Bank bank=new Bank(); bank.someMethod(this); } }
2.3构造器 • super指这个对象的父类 • super用来引用父类中的方法及变量数据. public class apple extends fruits { public apple(int price) { super(price); } } 表示使用超类的构造函数生成实例 • super必须是子类构造器的第一条语句
类构造器 class Singleton { private static Singleton obj; public static int counter1; public static int counter2; static { // 这就是class constructor // 在进入此class constructor之前,class已经被JVM // 配置好内存,所有的static field都会被先设定为0, // 所以此时counter1和counter2都已经是0,且singleton为null obj = new Singleton(); // 问题皆由此行程序产生 // counter1不会在此被设定为0 counter2 = 0; // counter2再被设定一次0(其实是多此一举) }
2.3构造器 • finalize()方法不是析构器 • 回收垃圾之前可能会调用对象的finalize()方法。(P60实例) • System.gc()强制回收垃圾。
2.4内部类 • 有名内部类 static的内部类是一个顶级类,它和包含类的成员是不相关的。 • 匿名内部类
作业 • 设计一个由自动测试排序算法性能(比较次数compare_count、交换次数exchange_count、探测次数probe_count)的测试类和排序类构成的类体系。 • 要求:用一个类来描述一个排序算法,类中的sort方法通过调用比较、交换方法来实现数组排序。排序类放入一个特定的包MySort中。