960 likes | 1.04k Views
第 7 章 Java 类的特性. 教学内容: 类的私有成员与公共成员 方法的重载 构造方法 实例成员与静态成员 重点: 重载 构造方法 难点: 静态成员 学时: 6. 7.1 类的私有成员与公共成员. 7.1.1 私有成员 保护成员变量不会被任意改变。 仅供自己使用,黑盒子。 7.1.2 公共成员 可以被所有类使用,透明。 7.1.3 友元 访问控制符 friendly ,可以省略。 同一包中可以访问。. class Student {
E N D
第7章 Java类的特性 教学内容: 类的私有成员与公共成员 方法的重载 构造方法 实例成员与静态成员 重点: 重载 构造方法 难点: 静态成员 学时:6
7.1 类的私有成员与公共成员 7.1.1 私有成员 保护成员变量不会被任意改变。 仅供自己使用,黑盒子。 7.1.2 公共成员 可以被所有类使用,透明。 7.1.3 友元 访问控制符friendly ,可以省略。 同一包中可以访问。
class Student { public String no,name,sex; public int age; void disp(){ System.out.print(no+“ ”+name+“ ”+sex+ “ ”+age); } } public class app1{ public static void main(String args[]){ Student s1 = new Stuednt(); s1.no=“9801”; s1.name = “张三”; s1.sex=“男”; s1.age = -8; //值被更改,不能控制值的范围 s1.disp(); } }
class Student { //私有成员 private String no,name,sex; private int age; void set(String pno,String pname,String psex,int page){ no = pno; name=pname ; sex=psex; if (page>0 && page<=60) age=page; else age=0; } void disp(){ System.out.print(no+“ ”+name+“ ”+sex+ “ ”+age); } } public class app1{ public static void main(String args[]){ Student s1 = new Stuednt(); s1.set(“9801”,“张三”,“男”,-8 ); s1.disp(); } }
class Student { //私有成员 private String no,name,sex; private int age; void setAge(int page){ if (page>0 && page<=60) age=page; else age=0; } int getAge () { … } } public class app1{ public static void main(String args[]){ Student s1 = new Stuednt(); s1.setAge(20); System.out.print( s1.getAge() ); } }
7.1.3 友元 若在类成员的前面加上访问控制符friendly,说明该成员是友元。
7.2 方法的重载 方法的重载中参数的类型是关键。 1 方法名相同 2 参数个数不同 或者 参数类型不同 或者 参数的顺序不同。 注意:与返回值无关。
class overloadDemo { int add (int x,int y){ return (x+y) ; } double add (double x,double y) { return (x+y); } public static void main(String args[]){ int a1=10,b1=2; double a2=9.43,b2=2.34 ; System.out.println( add(a1,b1) ); System.out.println( add(a2,b2) ); }
class A { int x,y; void set (int i , int j){ x=i; y = j; } void set( int i){ x=i; y=0; } void set(){ x=0;y=0;} }
class A { //改错2 int add (int i , int j){ return ( i + j ) ; } double add ( int i , int j){ double d; d = 3.14 * (i + j) ; } } class A { //改错1 int x , y; void set (int i,int j){ x=i; y = j; } void set( int m , int n){ x=m; y=n } } class A { //改错3 int no ; String name; void set (int pno , String pname){ no=pno; name = pname; } int set(String pname, int pno ){ no=pno; name = pname; return (pno) ; } }
class Cylinder { //app7_3.java 方法的重载 private double radius; private int height; private double pi=3.14; private String color; public double SetCylinder(double r, int h) { radius=r; height=h; return r + h ; } public void SetCylinder(String str) { color=str; } public void show( ) { System.out.println("圆柱的颜色为:"+color); } double area() { return pi* radius* radius; } double volume() { return area()*height; } }
public class app7_3 { public static void main(String args[ ]) { double r_h; Cylinder volu = new Cylinder(); r_h = volu.SetCylinder(2.5 , 5 ); volu.SetCylinder(“红色”); System.out.println("圆柱底和高之和="+r_h); System.out.println("圆柱体体积="+volu.volume()); volu.show(); } }
重载练习: 1 编写方法 proc , 当传入的参数为一个整数,则返回此数的阶乘。 当传入的参数为两个整数,则返回两数之和。 当传入的参数为两个float型,则返回两数的乘积。 写出主函数,测试。
7.3 构造方法 int a ; a = 3; 或: int a = 3; class A{ int x; void set( int d } { x = d;} public static void main()(String args[]) { A a1 = new A(); a1.set( 9); } 能否: A a1 = new A(9) ;
public class TDate { //如何建对象时 同时初始化? private int year =1900 private month , day ; public setDate(int yy, int mm, int dd){ year = yy;month=mm;day=dd; } public int getYear(){ return year; } public void print(){ System.out.print(year+”/”+month+”/”+day); } public static void main(String atgs[ ] ) { TDate d1 = new TDate( ) ; //对象数据成员值? d1.setDate ( 2010,4,10); } }
class Cylinder { //app7_4.java 构造方法的使用 private double radius; private int height; private double pi=3.14; public Cylinder(double r, int h) { //定义构造方法 radius=r; height=h; } double area() { return pi* radius* radius; } double volume( ) { return area()*height ; } } public class app7_4 { public static void main(String args[ ]) { Cylinder volu=new Cylinder(3.5, 8); //创建对象 并调用构造方法 System.out.println("圆柱底积="+ volu.area()); System.out.println("圆柱体体积="+volu.volume()); } }
7.3.1 构造方法的作用与定义 (1)构造方法的方法名与类名相同 (2)构造方法没有返回值,也不能写void (3)构造方法的作用是完成对类对象的初始化 (4)在创建一个类的对象的同时,系统会自动调用该类的构造方法为新对象初始化。 (5)构造方法一般不能由编程人员显式地直接调用,而是用new来调用;
class A{ int x; void set( int d } { x = d;} public static void main()(String args[]) { A a1 = new A(); a1.set( 9); } } class A{ int x; A ( int d } { x = d;} public static void main()(String args[]) { A a1 = new A(9 ); } }
public class TDate { //如何建对象时 同时初始化? private int year =1900 private month , day ; //public setDate(int yy, int mm, int dd){ TDate(int yy, int mm, int dd){ year = yy;month=mm;day=dd; } public int getYear(){ return year; } public void print(){ System.out.print(year+”/”+month+”/”+day); } public static void main(String atgs[ ] ) { TDate d1 = new TDate( 2010,4,10); d1.print(); } }
7.3.2 默认的构造方法 默认的构造方法没有参数,在其方法体中也没有任何代码,即什么也不做。 class A{ private int x; void show(){ Syetem.out.print(x); } } 有构造函数吗? 有默认构造函数 A( ) { }
class A{ private int x; A( ) { } void show(){ Syetem.out.print(x); } } 结论:1 类没有写构造方法,则系统自动加一个默认构造方法。 2 类中有构造方法,则系统不再自动加默认构造方法。 3 类一定有一个构造方法。
练习 class A{ public int x,y; A(int i,int j ){x =i; y=j;} void show(){ Syetem.out.print(x+” “+y); } } class B{ public int x,y; void show(){ Syetem.out.print(x+” “+y); } } 问题1: 类B有构造函数吗? 2: 类A有 A(){ } 吗?
7.3.3 构造方法的重载 class A{ public int x,y; A( ) {x=0 ; y=0; } A(int i ){x =i; y=0;} A(int i,int j ){x =i; y=j;} void show(){ System.out.print(x+” “+y); } public static void main(String args[]){ A t1 = new A(2); t1.show(); //new A; A t2 = new A(7,9); t2.show(); } }
class Cylinder { // app7_5.java private double radius; private int height; private double pi=3.14; String color; public Cylinder() { radius=1; height=2; color=”绿色”; } public Cylinder(double r, int h, String str) { radius=r; height=h; color=str; } public void getColor() { System.out.println("该圆柱的颜色为:"+color); } double area() { return pi* radius* radius; } double volume() { return area()*height; } }
public class app7_5 { //定义主类 public static void main(String args[ ]) { Cylinder volu1=new Cylinder(); //new Cylinder; System.out.println("圆柱1底面积="+ volu1.area()); System.out.println("圆柱1体积="+volu1.volume()); volu1.getColor(); Cylinder volu2=new Cylinder(2.5, 8,”红色”); System.out.println("圆柱2底面积="+ volu2.area()); System.out.println("圆柱2体积="+volu2.volume()); volu2.getColor(); } }
public class TDate { private int year ,month , day ; TDate( ){ year=1900 ; month=1;day=1; } TDate(int yy){ year = yy;month=1;day=1; } TDate(int yy, int mm){ year = yy;month=mm;day=1; } TDate(int yy, int mm, int dd){ year = yy;month=mm;day=dd; } public int getYear(){ return year; } public void print(){ System.out.print(year+”/”+month+”/”+day); } public static void main(String atgs[ ] ) { TDate d1 = new TDate(2010 ) ; TDate d2 = new TDate(2010,5); } } 日期类,初始化对象时,如不给参数,则默认1900-1-1; 给一个年份,则月份,日期都为1,给年份、月份,则日期为1,给年、月、日,则根据给定的设置。
练习: 1 构造函数重载,有何好处? 2 建立一个时间类, 1)构造函数要求: 可以仅给一个参数,表示时,分、秒为0。 可以仅给二个参数,表示时、分,秒为0。 可以仅给三个参数,表示时、分、秒。 可以不给参数,表示时、分,秒都为0。 2)打印如 23:11:30的时间 3) 建立测试: 建立时间 10:31:58 , 16:30:21 并打印。
7.3.4 从一个构造方法调用另一个构造方法 1 从某一构造方法内调用另一构造方法,是通过关键字this来调用的。 2 this 调用语句必须写在该方法的第一行 class A{ private int x; A(int i){ x = i; System.out.print("调用"); } A() {this( -1) ;} void print(){ System.out.print(x);} } public class test1{ public static void main(String args[]) { A a1 = new A(3); a1.print(); A a2 = new A(); a2.print(); } }
class Cylinder { // //app7_6.java private double radius; private int height; private double pi=3.14; String color; public Cylinder() { this(2.5, 5,”红色”); System.out.println(“无参构造方法”); } public Cylinder(double r, int h, String str) { System.out.println(“有参构造方法被调用了”); radius=r; height=h; color=str; } public void show() { System.out.println("圆柱底半径为:"+ radius); double area() { return pi* radius* radius; } double volume( ) { return area()*height; } }
【例7.6】续 35 public class app7_6 //主类 36 { 37 public static void main(String args[ ]) 38 { 39 Cylinder volu=new Cylinder(); 40 System.out.println("圆柱底面积="+ volu.area()); 41 System.out.println("圆柱体体积="+volu.volume()); 42 volu.show(); 43 } 44 }
7.3.5 公共构造方法与私有构造方法 1 构造方法一般都是公有(public)的! 2 如构造方法被声明为private,则在类外无法被调用,只能在该类的内部被调用。
class A{ private int x; private A(int i){ x = i; System.out.print("调用"); } A() {this( -1) ;} void print(){ System.out.print(x);} } public class test1{ public static void main(String args[]) { A a1 = new A(3); //? a1.print(); A a2 = new A(); a2.print(); }}
7.4 静态成员 static称为静态修饰符,它可以修饰类中的成员。 被static修饰的成员被称为静态成员,也称为类成员, 不用static修饰的成员称为实例成员。
7.4.1 实例成员 在类定义中如果成员变量或成员方法没有用static来修饰,则该成员就是实例成员。
7.4.2 静态变量 用static修饰的成员变量称为“静态变量”,也称为类变量。静态变量是隶属于类的变量,而不是属于任何一个类的具体对象。 静态变量的使用格式: 类名.静态变量 对象名.静态变量名
x 1 y 2 class A{ private int x , y ; static count=0; A(int d1 , int d2) { x=d1; y =d2;} void print(){ System.out.print(x+”,”+y); } } class Test { public static void main(String args[]){ A a1=new A(1,2); A a2=new A(5,3); A a3=new A(8,9); A.count =3; System.out.print(a1.count); x 5 a1 y 3 a2 a3 x 8 y 9 0 count 堆 栈
特点: • 1)所有该类的对象共享类变量。 • 2)通过类名被访问,可以不需创建类的实例(对象)。 • 3)类方法能直接访问类变量和类方法,但不能直接访问实例变量和实例方法。 • 类变量初始化 • 声明时初始化
class A{ //跟踪 A 被创建了几次 private int x , y ; static count=0; A(){ count ++;} A(int d1 , int d2) { x=d1; y =d2; count++;} void print(){ System.out.print(x+”,”+y); } } class Test { public static void main(String args[]){ A a1=new A(1,2); A a2=new A(5,3); A a3=new A(); System.out.print(a1.count); System.out.print(a3.count); }
class Cylinder { // app7_8.java静态变量的使用 private static int num=0; //声明num为静态变量 private static double pi=3.14; //声明pi为静态变量 private double radius; private int height; public Cylinder(double r, int h) { radius=r; height=h; num++; } public void count() { System.out.print(“创建了"+num+”个对象:”); } double area() { return pi* radius* radius;} double volume() { return area()*height; } } public class app7_8 { public static void main(String args[ ]) { Cylinder volu1=new Cylinder(2.5,5); volu1.count(); Cylinder volu2=new Cylinder(1.0,2); volu2.count(); } }
1 使用静态变量有何好处? 静态变量练习 2 class TDate { private static int year,month,day ; TDate( ){ year=1900 ; month=1;day=1; } TDate(int yy, int mm, int dd){ year = yy;month=mm;day=dd; } public void print(){ System.out.print(year+"/"+month+"/"+day); } } public class test1 { public static void main(String atgs[ ] ) { TDate d1 = new TDate(2010,4,7 ) ; TDate d2 = new TDate(2010,6,5 ) ; TDate d3 = new TDate(2012,12,12 ) ; d1.print();d2.print();d3.print(); } } 写出程序运行结果,并解释原因。
7.4.3 静态方法 static 修饰符修饰的方法是属于类的静态方法,又称为类方法。 静态方法实质是属于整个类的方法,而不加static修饰符的方法,是属于某个具体对象的方法。 • 1 通过类名被访问,不需创建类的实例(对象) • 2 静态方法能直接访问类变量和类方法,但不能直接访问实例变量和实例方法。 • 3 静态方法中不能使用 this , super • 4 调用方法: • 类名.静态方法(参数 ) • 对象名.静态方法(参数 )
class A{ //改错 类方法 int x; static int y=9; A( int i){ x = i;} static void f1(){ x++; y ++; f2(); } void f2 () { x++; y++; f1() ; } } class B{ public static void main(String args[]) { A a1(3); a1.f1(); a1.f2(); A.f1(); A.f2(); System.out.println( A.x); } } class A{ //类方法例题 int x; static int y=9; A( int i){ x = i;} static void f1(){ y ++;} void f2 () { x++;} } class B{ public static void main(String args[]) { A.f1(); System.out.println( A.y); } }
练习:类方法 编写一个类 myMath,类中提供如下方法: 1 计算阶乘的方法 int fact(int n) 。 2 计算 1+2+3+4 。。。n 的方法 int sum( int n) ; 3为整数排序的方法 sort,该方法接受一个待排序的一维数组,可以指定降序或升序。 sort ( int d[ ] , int direct) //direct=1 升序 , =2 降序 完成该类,并编写测试代码验证。要求使用这些方法时,不需要生成对象实例。 编写一个测试类 myApp, 计算8和12 的阶乘。 计算1+2+3。。+108; 生成10个50以内的随机数,分别以降序、升序排序输出。
class Cylinder { // app7_9.java 静态方法的使用 private static int num=0; private static double pi=3.14; private double radius; private int height; public Cylinder(double r, int h) { radius=r; height=h; num++; } public static void count() { System.out.println(“创建了"+num+”个对象”); } double area() { return pi* radius* radius; } double volume() { return area()*height; } } public class app7_9 { public static void main(String args[ ]) { Cylinder.count(); Cylinder volu1=new Cylinder(2.5,3); volu1.count(); System.out.println volu1.volume()); Cylinder volu2=new Cylinder(1.0,2); Cylinder.count(); System.out.println(volu2.volume()); } }
Math 类: 静态方法 • PI • ABS • Sin • Cos • max(int ,int) , min • random • sqrt
7.4.4 静态初始化器 对类的静态成员进行初始化。 静态初始化器与构造方法的不同: 1)构造方法是对每个新创建的对象初始化, 静态初始化器是对类自身进行初始化。 2)构造方法是在用new运算符创建新对象时由系统自动执行, 静态初始化器一般不能由程序来调用,它是在所属的类被加载入内存时由系统调用执行。 3)用new运算符创建多少个新对象,构造方法被调用多少次, 静态初始化器则在类被加载入内存时只执行一次,与创建多少个对象无关。 4)不同于构造方法,静态初始化器不是方法,因而没有方法名、返回值和参数。
public class test1{ int x; public static int y; static { y=9; } void print(){ System.out.print(x+","+y); } public static void main(String args[]) { test1 t1 = new test1(); t1.print(); } } 静态初始化器: class 类名 { static{ 程序块; } } static int y=9;
1 类A 有静态成员:数组 buffer ,要求在类加载时就产生20个100以内的随机数存储到数组 buffer中。 这段代码运行多少次? class A { int no; static String sex="男"; static double buffer[]=new double[20]; static { for (int i=0;i<20;i++) buffer[i] = Math.random() * 100; } public static void main(String args[]) { System.out.println( A.sex); for(int i=0;i<20;i++) System.out.println( A.buffer[i]); } }
2 类初始化器能否用构造方法代替? 3 改错 public class test1{ int x; public static int y; static { x=2; y=9; } void print() { System.out.print(x+","+y); } public static void main(String args[]) { test1.print(); } }
4 写出运行结果 public class Test{ private int x; static double y; static { y= Math.random() * 1000; System.out.println("B"); } Test( int i) { x = i ; System.out.println(“构造方法”); } static void printY(){ System.out.println( y ) ; } void printX(){ System.out.println( x ) ; } public static void main(String args[]) { System.out.println( "A"); Test.printY(); Test t1 = new Test(88 ); t1.printX(); } }