java--面向对象(3)--黑马程序员

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

面向对象(3)

主要内容:《 Math类的随机数、代码块、继承、this和super、方法重写的应用、方法重写、final关键字、多态 》

1 学习Math类的随机数功能

通过帮助文档:

1.Math类是在:java.lang包下,不需要导包(关于包,后面会学习);

2.此类没有构造方法,所有的可用方法都是static;通过类名就可以调用;

3.要学习使用:random()方法;

形参:没有

返回值:double。这个值:大于等于0.0并且小于1.0

1.获取1--100之间的随机数:

(int)(随机数 * 100) + 1

 1 class Demo {
 2     public static void main(String[] args) {
 3         for(int i = 0;i < 10 ;i++){
 4             System.out.println("获取一个随机数:" + Math.random());
 5         }
 6         System.out.println("*****获取10个1--100的随机数*****");
 7         for(int i = 0;i < 10 ;i++){
 8             System.out.println("第:" + (i + 1) + " 个:" + ((int)(Math.random() * 100) + 1));
 9         }
10     }
11 }

2 猜数字小游戏案例

猜商品价格:

1.系统先生成一个1--1000的一个整数值,作为一个商品价格;

2.用循环结构实现用户猜数;

3.每次循环做什么?

1).接收用户的猜的数字;

2).跟我们生成的数字进行判断,提示:高了,低了,相等

3).如果高了,或低了:继续下一次;

如果相等:结束循环

import java.util.Scanner;
class Demo
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        //1.系统先生成一个1--1000的一个整数值,作为一个商品价格;
int num = (int)(Math.random() * 1000) + 1;
        System.out.println("1--1000的商品价格已经生成,可以开始了......");
        //2.用循环结构实现用户猜数;
        while(true){
            System.out.print("你猜的数字:" );
            int n = sc.nextInt();
            //跟我们生成的数字进行判断,提示:高了,低了,相等
            if(n > num){
                System.out.println("高了!");
            }else if( n < num){
                System.out.println("低了!");
            }else{
                System.out.println("恭喜您猜中!价格为:" + num);
                break;
            }
        }
    }
}

3 代码块的概述和分类

代码块:

1.我们可以将一些代码封装到一对大括号中,这就叫:代码块。

{

//代码内容

}

2.代码块的分类:

1).局部代码块:在某个方法内,或某个语句内,出现的一对大括号,里面的代码就是代码块;

 1 public static void main(String[] args){
 2                 {
 3                     //局部代码块
 4                         int num = 10;
 5                         if(num>=10){
 6                         }
 7                         while(true){
 8                         }
 9                     }
10         //大家以前写程序时,一个常见的问题:
11                     if(num >= 10);
12                     {
13                     }
14                 }

2).构造代码块:定义在"类体中";在实例化对象时,被执行。

如果有构造方法同时存在,它会先于构造方法被执行;

它的作用同构造方法,就是用来初始化数据成员,或做一些先期的准备工作;

3).静态代码块:定义在"类体中";使用static关键字;

当第一次实例化此类对象时,会被执行一次;之后不会再被执行;

如果构造方法、普通代码块、静态代码块同时存在,那么执行顺序:

静态代码块-->普通代码块-->构造方法;

构造代码块虽然与构造方法的作用相同,但不能接收参数;

 1 class Student
 2 {
 3     String name;
 4     Student(){
 5         System.out.println("Student的构造方法");
 6     }
 7     {
 8         System.out.println("Student的构造代码块 name = " + name);
 9     }
10     static{
11     //    System.out.println("Student的静态代码块 name = " + name);//编译错误,静态的只能访问静态的;
12         System.out.println("Student的静态代码块");
13     }
14
15 }
16 class Demo
17 {
18     public static void main(String[] args)
19     {
20         Student stu = new Student();
21         System.out.println("**************************");
22         Student stu1 = new Student();
23         System.out.println("**************************");
24         Student stu2 = new Student();
25     }
26 }

4  继承的引入和概述以及案例演示

学生类:

属性:

学员编号:

姓名:(去掉)

性别:(去掉)

年龄:(去掉)

行为:

学习();

教师类:

属性:

老师编号:

姓名:(去掉)

性别:(去掉)

年龄:(去掉)

行为:

教学();

当设计好后,我们发现学生类和教师类中都包含了很多"重复"的元素:

String name;

int age;

char sex;

我们可以将这些重复的内容,进行进一步的抽取,再定义一个类,将这些共性的内容放到这个新类中,

之后让我们的学生类和教师类去"继承"那个新类。这时,我们的学生类和教师类中就不需要定义那些

重复的内容,继承后,将会从"父类"中继承。

进行抽取,定义新类:

人员类:

姓名:

性别:

年龄:

继承:

1.当一个类需要继承自另一个类时,使用关键字:extends

2.当一个类继承了某个类之后: 继承方:子类(派生类)

被继承方:父类(超类、基类)

3.当子类继承了父类后,就自动拥有了父类中允许被继承的成员:包括成员变量、成员方法。

继承的好处:

1.被子类继承后,达到了一个"代码重用"的目的;

2.为后面的"多态"提供了一个前提;

 1 class Person
 2 {
 3     String name;
 4     int age;
 5     char sex;
 6 }
 7 class Student extends Person
 8 {
 9     String stuNo;
10     void study(){
11         System.out.println("我们学习Java");
12     }
13 }
14 class Teacher extends Person
15 {
16     String teaNo;
17
18     void teach(){
19         System.out.println("我们教Java");
20     }
21 }
22 class Employee extends Person
23 {
24     String empNo;
25
26 }
27 class Demo
28 {
29     public static void main(String[] args)
30     {
31         Student stu = new Student();
32         stu.stuNo = "it001";//Student自有的
33         stu.name = "刘德华";//继承的
34         stu.age = 20;//继承的
35         stu.sex = ‘男‘;//继承的
36         System.out.println(stu.stuNo + "," + stu.name + "," + stu.age + "," + stu.sex);
37     }
38 }

5  继承的好处和弊端

继承的好处:

1.提高了代码的复用性;

2.提高了代码的可维护性;由于共性的内容被抽取到一个类中,如果放生更改,只需改父类一处即可;

继承的弊端:

1.一旦两个类具有了"子父关系",也就意味着有了"依赖关系"。子类依赖于父类。

当Student继承了Person后,Student就对Person产生了依赖,必须要有Person的存在,Student

才能编译通过。

6  Java中类的继承特点

Java中继承的特点:

1.Java只允许单继承:一个类只能继承自一个类;一个儿子只能有一个爹;

2.Java允许多级继承:Z继承自Y,Y继承自X;Z就拥有了Y 和X中允许被继承的成员;

class A{
    void fun(){
        System.out.println("A");
    }
}
class B{
    void method(){
    }
    void fun(){
        System.out.println("B");
    }
}
/*
class C extends A,B//编译错误。Java只允许单继承{
    //被继承的fun()方法将产生冲突
}
 1 //多级继承:
 2 class X
 3 {
 4     int numx = 10;
 5 }
 6 class Y extends X
 7 {
 8     int numy = 20;
 9 }
10 class Z extends Y
11 {
12 }
13 class Demo
14 {
15     public static void main(String[] args)
16     {
17         Z z = new Z();
18         System.out.println(z.numx + "," + z.numy);
19     }
20 }

7  继承的注意事项和什么时候使用继承

继承的注意事项:

1.子类只能继承父类所有非私有的成员(成员方法和成员变量):

2.子类不能继承父类的构造方法,但是可以通过super(后面讲)关键字去访问父类构造方法。

3.不要为了部分功能而去继承;

什么时候使用继承:

当"子类"相对于"父类"为"is a(是一个)"的关系时,可以使用继承:

我们说:Student是一个Person,就可以继承自Person

8 继承中类和类之间的关系(UML)

类和类之间的关系:

1."is a"(是一个):常见的就是"继承";

class Person{}

class Student extends Person{}

2."has a"(有一个):

class 学生{}

class 老师{}

//教室里面有:一个"老师",80名"学生"

class 教室{

int 楼层;//自有的属性

int 面积;//自有的属性

老师 tea = new 老师();//"老师"的对象最为"教室"的成员属性

学生[] stuArray = new 学生[80];//"学生"数组作为"教室"的成员属性

}

3."组成关系":一个类中没有"自有成员",全部都是其它的"类类型",由其它"类"组成的;

class CPU{}

class 硬盘{}

class 主板{}

.....

//"电脑"类全部都是由其它"类"组成

class 电脑{

CPU cpu;

硬盘 yp;

主板 zb;

....

}

4."依赖关系(关联关系)":

class 学生{}

class 老师{}

class 校长{

void talk(学生 xs){//由于talk方法接收的是"学生"类型的对象,我们说:"校长类"依赖于"学生类"

}

void talk(老师 ls){

}

}

9  继承中成员变量的关系

继承中成员变量的关系:

1.父类中的成员会被子类继承;

 1 class Fu
 2 {
 3     int num = 10000;
 4 }
 5 class Zi extends Fu
 6 {
 7     int num = 100;//子类的成员变量,覆盖了父类中同名的成员变量
 8
 9     //在Zi类内部访问num
10     void show(){
11         int num = 10;
12 class Demo {
13     public static void main(String[] args) {
14         Zi z = new Zi();
15 System.out.println(z.num);//在"Zi类"的外部访问num
16 System.out.println("******访问show()*********");
17         z.show();
18     }
19 }
20 System.out.println("num = " + num);//10:就近原则。先找"局部变量"-->"成员变量" --> "父类" System.out.println("本类的num : " + this.num);//本类的num:先在"本类"找,如果没有,会去"父类"找
21         System.out.println("访问父类的num :" + super.num);//访问父类的num
22 }}

10 this和super的区别和应用

super和this关键字:

1.super             1).在子类中使用;

2).存储的是"父类的引用";它指向父类对象空间;

3).在子类中,使用super可以访问父类的:成员变量、成员方法、构造方法

在子类中调用父类成员:

 1 成员变量:
 2                 class Fu{
 3                     int num = 10;
 4                 }
 5                 class Zi extends Fu{
 6                     void show(){
 7                 System.out.println(super.num);
 8                     }}
 9                             成员方法:
10                 class Fu{
11                     void fun1(){                System.out.println("Fu-->fun1()");
12                     }
13                 }
14                 calss Zi extends Fu{
15                     void show(){
16             super.fun1();//调用父类的成员方法;
17                     }
18                 }
19             调用父类的构造方法:
20                 class Fu{
21                 }
22                 class Zi extends Fu{
23                     Zi(){
24     super();//调用父类无参的构造方法;                System.out.println("Zi的构造方法");
25                         }
26                     }

4).有一种情况,子类必须显示的使用super()调用父类的构造方法:

当父类没有"无参构造方法"时;

1.当实例化子类对象时,Java回去实例化它的父类-->默认调用父类"无参构造方法";

2.如果父类没有"无参构造方法",那么Java 就没有办法调用;

3.这时,子类必须显示的使用super(),告诉Java编译器,调用哪个带参的构造方法,并传递什么样的参数;

5).当使用super调用父类的构造方法时,必须写在这个构造方法的:第一句有效代码;

this:                 1).任何类中都可以使用;

2).存储的"本类对象的引用";它指向的本类对象的空间;

3).this可以访问本类对象的:成员变量、成员方法、构造方法

this访问本类成员:

 1 成员变量:
 2                 class Student{
 3                     String name;
 4                     void show(){                System.out.println(this.name);
 5                     }
 6                 }
 7                 成员方法:
 8                 class Student{
 9                     void f1(){
10                     }
11                     void f2(){
12             this.f1();//调用本类的方法
13                     }
14                 }
15                 构造方法
16                 class Student{
17                     Student(){
18             System.out.println("无参的构造方法");
19                     }
20                     Student(int n){
21     Student();//掉用本类其它构造方法。不可以这样调用。
22         this();//调用本类无参的构造方法;                    System.out.println("带参的构造方法");
23                 }
24             }
25         4).调用本类其它构造方法使用this()。可以带参数。
26            注意:this()语句,必须是这个构造方法的第一条有效语句;
 1 class Fu
 2 {
 3     String name;
 4     Fu(String name){
 5         this.name = name;
 6         System.out.println("Fu的构造方法");
 7     }
 8     void show(){
 9         System.out.println("Fu-->show()");
10     }
11 }
12 class Zi extends Fu
13 {
14     Zi(){
15         super("匿名");
16     }
17     Zi(String name){
18         //直接传给了父类。子类必须显示的使用super调用父类的带参的构造方法。否则编译错误;
19         super(name);
20     //    this();//注意:super()和this()语句不能同时存在;
21         System.out.println("Zi的构造方法");
22
23     }
24     void fun(){
25         super.show();//可以通过super关键字访问父类的成员方法;
26     }
27 }
28 class Demo
29 {
30     public static void main(String[] args)
31     {
32         Zi z = new Zi();
33
34     }
35 }

11 this和super以及重写和重载的面试题

super和this关键字:

1.super:

1).在子类中使用;

2).存储的是"父类的引用";它指向父类对象空间;

3).在子类中,使用super可以访问父类的:成员变量、成员方法、构造方法

在子类中调用父类成员:

 1 成员变量:class Fu{
 2     int num = 10;
 3     }
 4     class Zi extends Fu{
 5     void show(){                        System.out.println(super.num);
 6     }}
 7 成员方法:
 8     class Fu{
 9         void fun1(){
10     System.out.println("Fu-->fun1()");
11     }}
12     calss Zi extends Fu{
13         void show(){
14     super.fun1();//调用父类的成员方法;
15     }}
16 调用父类的构造方法:
17     class Fu{
18     }
19     class Zi extends Fu{
20         Zi(){
21     super();//调用父类无参的构造方法;
22     System.out.println("Zi的构造方法");
23                         }
24                     }

4).有一种情况,子类必须显示的使用super()调用父类的构造方法:

当父类没有"无参构造方法"时;

1.当实例化子类对象时,Java回去实例化它的父类-->默认调用父类"无参构造方法";

2.如果父类没有"无参构造方法",那么Java 就没有办法调用;

3.这时,子类必须显示的使用super(),告诉Java编译器,调用哪个带参的构造方法,并传递什么样的参数;

5).当使用super调用父类的构造方法时,必须写在这个构造方法的:第一句有效代码;

this:

1).任何类中都可以使用;

2).存储的"本类对象的引用";它指向的本类对象的空间;

3).this可以访问本类对象的:成员变量、成员方法、构造方法this访问本类成员:

 1 void f2(){
 2                     this.f1();//调用本类的方法
 3                     }
 4                 }
 5                 构造方法
 6                 class Student{
 7                     Student(){
 8             System.out.println("无参的构造方法");
 9                     }
10                     Student(int n){
11 //    Student();//掉用本类其它构造方法。不可以这样调用。
12 this();//调用本类无参的构造方法;
13 System.out.println("带参的构造方法");
14                     }
15                 }
16 成员变量:
17                 class Student{
18                     String name;
19                     void show(){
20                 System.out.println(this.name);
21                     }
22                 }
23 成员方法:
24                 class Student{
25                     void f1(){}
26                     void f2(){
27                     this.f1();//调用本类的方法
28                     }
29                 }
30                 构造方法
31                 class Student{
32                     Student(){
33             System.out.println("无参的构造方法");
34                     }
35                     Student(int n){
36 //    Student();//掉用本类其它构造方法。不可以这样调用。
37 this();//调用本类无参的构造方法;
38 System.out.println("带参的构造方法");
39                     }
40                 }

4).调用本类其它构造方法使用this()。可以带参数。

注意:this()语句,必须是这个构造方法的第一条有效语句;

class Fu{
    String name;
    Fu(String name){
        this.name = name;
        System.out.println("Fu的构造方法");
    }
    void show(){
        System.out.println("Fu-->show()");
    }
}
class Zi extends Fu{
    Zi(){
        super("匿名");
    }
    Zi(String name){
        //直接传给了父类。子类必须显示的使用super调用父类的带参的构造方法。否则编译错误;
        super(name);
    //    this();//注意:super()和this()语句不能同时存在;
        System.out.println("Zi的构造方法");
            }
    void fun(){
        super.show();//可以通过super关键字访问父类的成员方法;}
}
class Demo
{
public static void main(String[] args)
    {
        Zi z = new Zi();
    }
}

12 方法重写的应用

1.子类中出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法重写(复写);

2.重写的格式:

1).返回值类型  方法名 ,形参列表:必须完全一致;

A."返回值类型"和"方法名"相同,"参数列表"不同:编译通过。类似于"重载"

B."方法名"和"参数列表"相同,"返回值类型"不同:编译错误。如果"方法名"和"形参列表"相同,要求"返回值类型"必须相同;

2).访问修饰符:要求:

子类的方法所具有的访问修饰符必须跟父类的方法的访问修饰符相同,或更宽的访问修饰符;

public,protected,(默认),private(从宽到窄)

 1 class Fu{
 2     void show(int a){
 3     }
 4 }
 5 class Zi extends Fu{
 6     //编译可以通过。类似于"重载"
 7     void show(String s){
 8     }
 9     //编译错误。按照"重写"的格式进行要求。
10     /*
11     int show(int a){
12     }
13     */
14     //重写
15     public void show(int a){
16     }
17 }
18 class Demo {
19     public static void main(String[] args) {
20         Zi z = new Zi();
21         z.show(10);//Fu
22         z.show("刘德华");//Zi
23     }
24 }

铺垫的小知识:

第一个:成员变量有基本类型和引用类型的。

class Demo {

//基本类型

int x = 10;

//引用类型

Student s = new Student();

}

第二个:类的初始化过程

加载class文件

堆中开辟空间

变量的默认初始化

变量的显示初始化

构造代码块初始化

构造方法初始化

第三个:遇到extends,就要知道,先初始化父类数据,然后初始化子类数据。

分层初始化。

super在这里仅仅表示要先初始化父类数据。

13 继承中成员方法关系

1.子类可以覆盖父类中的同名的方法;

2.通过子类对象访问方法时:

1).先在子类中找,如果没有

2).到父类中找。

3).如果父类也没有,报错;

 1 class Fu{
 2     void fun1(){
 3         System.out.println("Fu-->fun1()");
 4     }
 5 }
 6 class Zi extends Fu{
 7     //方法的:重写
 8     void fun1(){
 9         System.out.println("Zi-->fun1()");
10     }
11 }
12 class Demo {
13     public static void main(String[] args) {
14         Zi z = new Zi();
15         z.fun1();
16     }
17 }

14 方法重写的注意事项

方法重写的注意事项

1.父类中私有方法不能被重写。

2.子类重写父类方法时,访问权限不能更低。必须是具有:相同,或更宽的访问权限;

3.父类静态方法,子类也必须通过静态方法进行重写。       (其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解)

class Fu{
    private void show(){
        System.out.println("Fu--private show()");
    }

    public static void fun(){
    System.out.println("Fu-->public static fun()");
    }
}
class Zi extends Fu{
    //可以定义跟父类相同的方法,但这不是"重写
public void show(){
        System.out.println("Zi--show()");
    }
    //子类重写父类中的静态的方法
    public static void fun(){
        System.out.println("Zi-->public static fun()");
    }
}
class Demo
{
    public static void main(String[] args)
    {
        Zi z = new Zi();
        z.show();

        z.fun();
        //通过"子类的类名",调用父类的静态方法
        Zi.fun();
    }
}

15 方法重写和方法重载的区别?方法重载能改变返回值类型吗?

1.Overload:重载

2.Override:重写

1.重载:在一个类中,可以定义多个同名的方法,但形参列表不完全相同;跟返回值无关;

2.重写:在子类中,可以定义跟父类一模一样的方法(返回值类型、方法名、形参列表完全相同),这时

子类的方法会覆盖父类中同名的方法。

16 this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。

1.this:

1).在任何类中使用;

2).存储的是本类对象的引用;

3).可以访问本对象的成员变量、成员方法、构造方法;

2.super:

1).在子类中使用;

2).存储的是父类对象的引用;

3).可以访问父类对象的成员变量、成员方法、构造方法;

17 final关键字

final关键字:

1.可以修饰:

1).成员变量:此变量拥有最终的值。是一个"常量"。其值是不能被修改的。或者只能被赋值一次;(也分为基本类型和引用类型)

2).成员方法:表示最终的方法。不能被"重写"。

3).类:表示最终的类;不能被"继承".

4).局部变量:

A.普通局部变量:

A-1:修饰基本数据类型:其值不能被更改;

A-2:修饰引用数据类型:其地址不能被更改;

B.方法的形参:

B-1:修饰基本数据类型:其形参的值不能被更改;

B-2:修饰引用数据类型:其形参的地址不能被更改;

 1 class Person{
 2     final void show(){
 3 System.out.println("我是传智播客的一员");
 4     }
 5 }
 6 class Student extends Person{
 7     String name;
 8     static final String SCHOOL_NAME = "传智播客--北京校区";
 9     final int num;
10     double aaa;
11         Student(){
12         num = 20;
13     }
14 System.out.println(Student.SCHOOL_NAME);
15     //    Student.schoolName = "北京校区";
16     System.out.println(Student.SCHOOL_NAME);
17         final int num = 10;//final修饰局部变量--基本数据类型
18         System.out.println("num = " + num);
19     //    num = 20;//其值不能改变
20         final Student stu = new Student();//final修饰局部变量--引用数据类型
21 //试图重写父类的final方法
22     //编译错误,无法覆盖
23     /*
24     void show(){
25     //num = 10;//不能在成员方法中赋值
26     }
27     */
28 }
29 class Demo
30 {
31     public static void main(String[] args)
32     {
33 stu.name = "刘德华";//堆空间的内容是可以改的
34         stu.name = "张学友";
35
36     //    stu = new Student();//其指向的地址不可更改;
37 int x = 10;
38         method(x);
39         System.out.println("x = " + x);

18 多态的概述及其代码

多态的概念:

1.之前我们定义子类,继承自父类。

在使用时:

子类  zl = new 子类();

2.使用多态:可以定义一个"父类类型的引用",指向它的"子类的对象",这种形式就叫:多态

父类 fl = new 子类();

Animal a1 = new Cat();

多态的前提和体现;

1.一定要存在"继承关系";

2.方法重写;

class Animal{
    String name;
    int age;
}
class Cat extends Animal{
}
class Demo {
    public static void main(String[] args)
    {
        //之前的形式
        Cat cat = new Cat();
int[] array = {1,2,3,4};
        method(array);
        System.out.println(array[0]);
    }
    public static void method(final int a){
    //    a = 100;//编译错误:值不能被修改;
    }
    public static void method(final int[] arr){
        arr[0] = 1000;//OK的。堆空间的内容是可以被修改的。
        arr = new int[3];//编译错误:地址不能被修改;
    }
}
//多态的形式
        Animal a1 = new Cat();
        a1.name = "波斯猫";
        a1.age = 2;
    System.out.println(a1.name + "," + a1.age + "岁");
    }
}

19 多态中的成员访问特点

成员变量的访问特点:

1.成员变量:编译看左边(父类中一定要有,否则编译错误);运行看左边(如果子类覆盖父类的成员变量,打印的是父类的)

2.成员方法:编译看左边(父类中一定要有,否则编译错误);运行时看右边(如果子类重写父类的成员方法,调用的是子类的)

3.静态方法:编译看左边(父类中一定要有,否则编译错误);运行时看左边(如果子类重写父类中的静态方法,调用的是父类的)

总而言之:

1.当多态时,访问的成员(成员变量、成员方法)父类中必须要有,否则编译错误。

运行时,只有"被覆盖的普通成员方法"访问的是"子类的",其它都是"父类"的。

 1 class Person{
 2     String name;
 3     int num = 10;
 4     void show(){
 5     System.out.println("Person-->show()");
 6     }
 7     static void method(){
 8     System.out.println("Person --> method()");
 9     }
10 }
11 class Student extends Person{
12     String stuNo;//学员编号
13     int num = 20;
14 void fun(){
15         System.out.println("Student --> fun()");
16     }
17
18
19 //    p1.stuNo = "it001";//编译错误。编译看左边。如果父类中没有,编译错误
20         System.out.println(p1.name);
21         System.out.println(p1.num);//运行看左边。打印的仍然是父类的
22
23         p1.show();//OK的,父类中有show()。运行时,调用的是子类的。
24     //    p1.fun();//不可以。编译看左边-->父类中如果没有,则编译错误;
25
26         p1.method();//打印是父类的。由于method是静态方法。静态方法是属于"类"的。所以它还是看具体的"类型"
27     }
28 }
29 //子类重写父类的show()
30     void show(){
31         System.out.println("Student --> show()");
32     }
33     //重写父类中的静态方法
34     static void method(){
35         System.out.println("Student --> method()");
36     }
37 }
38 class Demo {
39     public static void main(String[] args)
40     {
41         //以前的形式
42         Student stu = new Student();
43         stu.name = "张三";
44 //多态的形式
45         Person p1 = new Student();
46         p1.name = "李四";

20 多态的好处和弊端

 1 多态的好处class Animal{
 2     String name;
 3     int age;
 4     char sex;
 5 }
 6 class Cat extends Animal{}
 7
 8 class Dog extends Animal{
 9 }
10 class Demo {
11     public static void main(String[] args) {
12         //使用多态
13         Cat a1 = new Cat();//a1 = 0x2233
14         Dog a2 = new Dog();//a2 = 0x4455
15         a1.name = "波斯猫";
16         a1.age = 3;
17         a1.sex = ‘雄‘;
18     //    System.out.println(a1.name + "," + a1.age + "岁," + a1.sex);
19     //    printCat(a1);
20         printAnimal(a1);//printAnimal(0x2233)
21         a2.name = "阿拉斯加";
22         a2.age = 3;
23  a2.sex = ‘雌‘;
24 //System.out.println(a2.name + "," + a2.age + "岁," + a2.sex); //    printDog(a2);
25 printAnimal(a2);//printAnimal(0x4455)
26     }
27     //定义一个方法,可以打印猫的信息
28 //    public static void printCat(Cat c){
29     //利用"多态"的特性。一个方法的形参可以声明为某个"父类"类型。就表示:可以接收任何的它的子类对象的引用。
30     public static void printAnimal(Animal a){//Animal a = 0x2233(new Cat())//Animal a = 0x4455(new Dog());
31     System.out.println(a.name + "," + a.age + "岁," + a.sex);
32     }}
 1 多态的弊端:1.当多态时,不能访问子类特有成员;
 2                 class A{
 3                 int n = 10;
 4             }
 5             class B extends A{
 6                 int m = 20;
 7             }
 8             main(){
 9                 A a = new B();
10         System.out.println(a.m);//编译错误。
11             }
12     2.可以通过转型,去访问子类特有成员;

多态中向上转型和向下转

多态中的类型转换:

1.向上转型(隐式的,自动的):"父类"类型的变量,存储"子类对象"的引用;

Animal a = new Cat();//向上转型;

2.向下转型(显示的,强制转换):如果我们确定一个"父类"类型的变量,存储了某个具体的"子类对象"的引用。

我们可以将这个"父类类型"强制转换为它所存储的"子类类型";              Animal a = new Cat();//向上转换

Cat c = (Cat)a;//向下转换

Dog d = (Dog)a;//错误。

3.向下转型由于要使用"强制转换",这就有了隐藏的危险。如果类型不匹配,将在运行时异常:ClassCastException。

Java为我们提供了一种方式,在强制转换前,可以先进行判断,如果为true,再进行转换。

使用关键字:instanceof

它是双目运算符:左操作数 instanceof 右操作数

左操作数:一般是一个"变量名";

右操作数:是某个"类名"

整体的意思:"左操作数"是否是"右操作数"的类型:是:返回true,否则:返回:false

Animal a = new Cat();

if(a instanceof Cat){

Cat c = (Cat)a;//转换是安全的;

}

if(a instanceof Dog){

Dog d = (Dog)a;

}

 1 class Animal{
 2 }
 3 class Cat extends Animal{
 4     int m = 10;
 5 }
 6 class Dog extends Animal{
 7 }
 8 class Demo {
 9     public static void main(String[] args) {
10         Animal a = new Cat();
11     //    System.out.println(a.m);//编译错误。不能访问子类特有成员。
12         Cat c = (Cat)a;//OK的
13     //    Dog d = (Dog)a;//运行时异常:ClassCastException:
14         //使用instanceof关键字
15         if(a instanceof Cat){
16             System.out.println("经判断,是Cat类型");
17             Cat c1 = (Cat)a;//转换是安全的;
18         }
19         if(a instanceof Dog){
20             System.out.println("经判断,是Dog类型");
21             Dog d = (Dog)a;
22         }
23     }
时间: 2024-10-27 13:27:51

java--面向对象(3)--黑马程序员的相关文章

黑马程序员_关于黑马java班入学测试技术分享-后五(二)

??????????????????????????????????????????????????????????????????????????-----Java培训.Android培训.iOS培训..Net培训.期待与您交流! 作为本人首篇黑马技术博客有必要交代一下背景.个人理解博客的用作在于于己在于交流,于他在于学习,在交流学习中共同成长.下面进入正题.本文主要是介绍在做黑马入门测试时的一些问题(这个应该不是泄露题库吧). 本文只要是讲述黑马程序员基础测试题的6-10题,回过头来分析明显

黑马程序员_Java面向对象思想

面向对象要把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法 . 1.人在黑板上画圆 对于这个设计,上面有Person, Blackborad , Circle三个对象 动词 : 画 因为画的动作的数据:坐标(x,y),半径(randius) 是Circle拥有的数据,所以 draw()方法应该属于Circle对象,而不是动作的发出者Person. 注意:[动作发出者往往会委托动作承受者 ] 2.司机紧急刹车 对于这个设计,上面有Driver, Car两个对象 动词 : 刹车 因为刹

黑马程序员-OC面向对象继承关系和组合关系笔记

继承关系是描述类和类之间的关系,两个类分别称为子类和父类,子类继承了父类,子类就拥有了父类的属性和方法: 继承的关系特点描述出来就是:** "是" **  (例如:学生类 是 人类) 组合关系描述的语句是:**** "拥有" ***  (例如:学生有成绩这个属性,而成绩属性本来就是一个成绩类的对象 ) 继承示例代码: #import <Foundation/Foundation.h> //Animal类的声明 @interface Animal : NS

黑马程序员____第一阶段Java开发前奏(1)

  黑马程序员____第一阶段Java开发前奏(1) ⒈软件开发:        软件是由一系列按照特定顺序组织的计算机数据和指令的集合,软件开发就是制作软件.软件的出现实现了人与计算机之间的交互.    ⒉人机交互方式:        图形化界面和命令行方式,图形化界面简单直观,使用者易于接受,容易上手操作.命令行方式需要有一个控制台,输入特定的指          令,让计算机完成一些操作,较为麻烦,需要记住一些命令.    3.常用的DOS命令:     dir:列出当前目录下的文件以及文

黑马程序员–Java之多线程09

黑马程序员–Java之多线程09 一.线程和进程 在Java中,并发机制非常重要,程序员可以在程序中执行多个线程,每一个线程完成一个功能,并与其他线程并发执行,这种机制被称为多线程.多线程就是指一个应用程序中有多条并发执行的线索,每条线索都被称作一个线程,它们会交替执行,彼此间可以进行通信.多线程是非常复杂的机制,在每个操作系统中的运行方式也存在差异,window操作系统是多任务操作系统,它以进程为单位.一个进程是一个包含有自身地址的程序,每个独立执行的程序都称为进程,也就是正在执行的程序.系统

黑马程序员——java基础——异常

黑马程序员--java基础--异常 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 异常 就是不正常.程序在运行时出现的不正常情况.其实就是程序中出现的问题.这个问题按照面向对象思想进行描述,并封装成了对象.因为问题的产生有产生的原因.有问题的名称.有问题的描述等多个属性信息存在.当出现多属性信息最方便的方式就是将这些信息进行封装.异常就是java按照面向对象的思想将问题进行对象封装. 异常体系 --------java.lang.Thro

黑马程序员-面向对象的特征

Java面向对象 面向对象是一种程序设计方法,或者是程序设计规范,其基本思想是使用对象.类.继承.封装.多态等基本概念来进行程序设计. 面向对象是一种符合人们思考习惯的思想,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者 完成需求时: ? 先要去找具有所需的功能的对象来用. ? 如果该对象不存在,那么创建一个具有所需功能的对象. ? 这样简化开发并提高代码的复用. 面向对象的开发过程其实就是不断的创建对象,使用对象,指挥对象做事情.设计的过程其实就是在管理和维护对象之间的关系. 面向对象

黑马程序员-java 7K面试题之交通灯管理系统

------- android培训.java培训.期待与您交流! -------- 交通灯管理系统 模拟实现十字路口的交通灯管理系统逻辑,具体需求如下: 1. 异常随机生成按照各个路线行驶的车辆. 例如: 由南向而来去往北向的车辆----直行车辆 由西向而来去往南向的车辆----右转车辆 由东向而来去往南向的车辆----左转车辆 .......  ...... 2. 信号灯忽略黄灯,只考虑红灯和绿灯. 3. 应该考虑左转车辆控制信号灯,右转车辆不受信号灯控制. 4. 具体信号灯控制逻辑与现实

黑马程序员-java 7K面试题之银行业务调度系统

------- android培训.java培训.期待与您交流! -------- 银行业务调度系统 模拟实现银行业务调度系统逻辑,具体需求如下: 1. 银行有6个业务窗口,1-4号窗口为普通窗口,5号窗口为快速窗口,6号窗口为VIP窗口. 2. 有三种对应类型的客户:VIP客户.普通客户.快速客户(办理如交水电费.电话费之类业务的客户). 3. 异步随机生成各种类型的客户,生成各类型用户的概率比率为: VIP客户:普通客户:快速客户=1:6:3 4. 客户办理业务所需时间有最大值和最小值,

黑马程序员------Java反射学习总结(一)

-------------------------Java培训.Android培训,期待与您交流!----------------------------- 一.反射的概念 1) Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 2)一句话来讲,反射就是将Java类中的各个成分映射成相应的Java类. 3)即在Java中,描述事物的各种