6.面向对象编程(下)2

6.面向对象编程(下)2

1:final关键字(掌握)

(1)final的含义

final是最终的意思,可以修饰类,方法,变量。

(2)特点

被final修饰的类、变量和方法将具有以下特性。

●final修饰的类不能被继承。

●final修饰的方法不能被子类重写(也叫覆盖)。

●final修饰的变量不能被重新赋值。

 

A:被final修饰的类,不能被继承。

举例子:

 

final class Fu {

}

 

class Zi extends Fu {// 错误: 无法从最终Fu进行继承

}

 

class FinalDemo {

         public static void main(String[] args){

         }

}

 

B:被final修饰的方法,该方法是不能被重写的。

举例子:

          继承中方法有一个现象:方法重写。

          父类的功能,就会被子类给覆盖掉。

          但是被final修饰的方法是不可以被重写!

class Fu {

         public final void show(){

                  System.out.println("Fu show");

         }

}

 

class Zi extends Fu {

         //被final修饰的方法是不可以被重写的

         public void show(){ // error,Zi中的show()无法覆盖Fu中的show()

                  System.out.println("Zi show");

         }

}

 

class ZiDemo {

         public static void main(String[] args){

                  Zi z = new Zi();

                  z.show();

         }

}

 

         C:被final修饰的变量不能被重新赋值。因为这个变量其实就是常量。

举例子:

class Fu {

         final public int num = 10;

          

}

 

class Zi extends Fu {

         public void show(){

                 

                  System.out.println(num);

                  //num = 100; // 错误: 无法为最终变量num分配值

                  System.out.println(num);

         }

}

 

class FinalDemo {

         public static void main(String[] args){

                  Zi z = new Zi();

                  z.show();

         }

}

(3)经典案例

1:final修饰局部变量

                  ●在方法内部,该变量不可以被改变。

                  ●在方法声明上,分别演示基本类型和引用类型作为参数的情况

                          a: 局部变量是基本类型,基本数据类型的值不能发生改变

b: 局部变量是引用类型 地址值不能发生改变,但是对象的内容是可以改变的

 举例子:

a:final修饰的局部变量为基本数据类型时

class FinalTest {

         public static void main(String[] args){

                  //局部变量是基本数据类型

                  int x = 10;

                  x = 100;

                  System.out.println(x);//100

                  final int y = 10;

                  //错误: 无法为最终变量y分配值

                  //y = 100;

                  System.out.println(y);//10

         }

}

                           

举例子:

b:final修饰的局部变量为引用类型的数据时

class Student {

         int age = 10;

}

 

class FinalTest {

         public static void main(String[] args){

                  //局部变量是引用数据类型

                  Student s = new Student();

                  System.out.println(s.age);//10

                  s.age = 100;

                  System.out.println(s.age);//100

                  System.out.println("--------------");

 

                  final Student ss = new Student();

                  System.out.println(ss.age);//10

                  ss.age = 100;

                  System.out.println(ss.age);//100

 

                  //重新分配内存空间

                  //ss = new Student();// 错误: 无法为最终变量ss分配值

                  //对象的地址不能变,但是对象里面的内容却是可以变的

         }

}

2:final修饰变量的初始化时机

a: 被final修饰的变量只能赋值一次(只能初始化一次)。

b:  final修饰变量的初始化时机:在构造方法完毕前。(引申:针对非静态的常量)

 

举例子:

例1:

class Demo {

         int num = 10;

         final int num2 = 20;

 

         public Demo(){

                  num = 100;

                  // 错误: 无法为最终变量num2分配值

                  //num2 = 200;

         }

}

 

class FinalTest1 {

         public static void main(String[] args){

                  Demo d = new Demo();

                  System.out.println(d.num);//100,做初始化先做成员变量初始化,再做构造函数初始化

                  System.out.println(d.num2);//20

         }

}

 

例2:(思考下为什么例1会报错,可是例2不会报错)

class Demo {

 

         int num;

         final int num2;

 

         public Demo(){

                  num = 100;

                  num2 = 200;

         }

}

 

class FinalTest2 {

         public static void main(String[] args){

                  Demo d = new Demo();

                  System.out.println(d.num);//100

                  System.out.println(d.num2);//200

         }

}

例3:(思考:为什么例3 又报错了呢。总结:final修饰变量的初始化时机)

class Demo {

         int num ;

         final int num2 ;

 

         {

                  num2 = 10;     

         }

 

         public Demo(){

                  num = 100;

                  //无法为最终变量num2分配值

                  //num2 = 200;

         }

}

 

class FinalTest3 {

         public static void main(String[] args){

                  Demo d = new Demo();

                  System.out.println(d.num);//100

                  System.out.println(d.num2);//10

         }

}

final修饰变量的初始化时机:在构造方法完毕前。

那么赋值一般什么时候给呢:

1.定义的时候。(推荐)

2.构造方法中。

        

2:多态(掌握)

         (1)同一个对象在不同时刻体现出来的不同状态。

         (2)多态的前提:

                  A:有继承或者实现关系。

                  B:有方法重写。

                  C:有父类或者父接口引用指向子类对象。

                   

                          父 f = new 子();

 

                  多态的分类:

                          a:具体类多态

                                   class Fu {}

                                   class Zi extends Fu {}

                                  

                                   Fu f = new Zi();

                           b:抽象类多态

                                   abstract class Fu {}

                                   class Zi extends Fu {}

                                  

                                   Fu f = new Zi();

                          c:接口多态

                                   interface Fu {}

                                   class Zi implements Fu {}

                                  

                                   Fu f = new Zi();

         (3)多态中的成员访问特点

                  A:成员变量

                          编译看左边,运行看左边

                  B:构造方法

                          子类的构造都会默认访问父类构造

                          创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。

                  C:成员方法

                          编译看左边,运行看右边

                  D:静态方法

                          编译看左边,运行看左边

                           (静态和类相关,算不上重写,所以,运行访问的还是左边的)

                  (运行)只有成员方法是特殊的,为什么?

                          因为成员方法存在方法重写。

举例子:

a. 成员变量

class Fu {

      public int num = 100;

 

      public void show(){

               System.out.println("show Fu");

      }

}

 

class Zi extends Fu {

      public int num = 1000;

      public int num2 = 200;

 

      public void show(){

               System.out.println("show Zi");

      }

}

 

class DuoTaiDemo {

public static void main(String[] args){

          Fu f = new Zi();

          System.out.println(f.num);

          //编译看左边,左边Fu类型没有num2

          //System.out.println(f.num2);//error.找不到符号

}

}

c.  成员方法

举例子:

class Fu {

      public void show(){

               System.out.println("show Fu");

      }

}

 

class Zi extends Fu {

      public void show(){

               System.out.println("show Zi");

      }

 

      public void method(){

               System.out.println("method zi");

      }

}

 

class DuoTaiDemo {

public static void main(String[] args){

          Fu f = new Zi();

          //编译看左边,(重写)运行看右边

          f.show();

          //f.method();//编译看左边,左边父类方法找不到符号

}

}

d. 静态方法

举例子:

class Fu {

 public static void function(){

          System.out.println("function Fu");

 }

}

 

class Zi extends Fu {

  public static void function(){

          System.out.println("function Zi");

 }

}

 

class DuoTaiDemo {

public static void main(String[] args){

          Fu f = new Zi();

          f.function();//function Fu

}

}

(4)多态的好处:

                  A:提高代码的维护性(继承体现)

                  B:提高代码的扩展性(多态体现)

(5)多态的弊端:

                  父不能使用子的特有功能。

举例子:

class Fu{

         public void show(){

                  System.out.println("show fu");

         }

}

 

class Zi extends Fu{

         public void show(){

                  System.out.println("show zi");

         }

 

         public void method(){

                  System.out.println("method zi");

         }

}

 

class DuoTaiDemo3{

         public static void main(String[] args){

                  Fu f = new Zi();

                  f.show();

                  //f.method();//错误,不能使用子类的特有功能

         }

}

                  现象:

                          子可以当作父使用,父不能当作子使用。

         (6)多态中的转型问题

                  A:向上转型     父类引用指向子类对象

                          从子到父  Fu f = new Zi();

                  B:向下转型  父类引用强制转换为子类对象。

                          从父到子  Zi z = (Zi) f;//要求该f必须是能够转换为Zi的。

举例子:

class Fu{

         public void show(){

                  System.out.println("show fu");

         }

}

 

class Zi extends Fu{

         public void show(){

                  System.out.println("show zi");

         }

 

         public void method(){

                  System.out.println("method zi");

         }

}

 

class DuoTaiDemo3{

         public static void main(String[] args){

                  Fu f = new Zi();

                  f.show();

                  //f.method();//不能使用子类的特有功能

 

                  //你能够把子的对象赋值给父亲,那么我能不能把父的引用赋值给子的引用呢?

//把父类的引用强制转换为子类的引用。

                  Zi z = (Zi)f;

                  z.show();

                  z.method();

         }

}

          

         (7)多态的练习

A:猫狗案例

举例子:

class Animal {

         public void eat(){

                  System.out.println("吃饭");

         }

}

 

class Dog extends Animal {

         public void eat(){

                  System.out.println("狗吃肉");

         }

 

         public void lookDoor(){

                  System.out.println("狗看门");

         }

}

 

class Cat extends Animal {

         public void eat(){

                  System.out.println("猫吃鱼");

         }

 

         public void playGame(){

                  System.out.println("猫捉迷藏");

         }

}

 

class DuoTaiTest {

         public static void main(String[] args){

                  //定义为狗

                  Animal a = new Dog();

                  a.eat();

                  System.out.println("--------");

                  //还原成狗

                  Dog d = (Dog) a;

                  d.eat();

                  d.lookDoor();

                  System.out.println("--------");

                  //变成猫

                  a = new Cat();

                  a.eat();

                  System.out.println("-------");

                  //还原成猫

                  Cat c = (Cat) a;

                  c.eat();

                  c.playGame();

 

         }

}

B:北方人和南方人案例

/*

         不同地方饮食文化不同的案例

*/

class Person {

         public void eat(){

                  System.out.println("吃饭");

         }

}

 

class SouthPerson extends Person {

         public void eat(){

                  System.out.println("炒菜,吃米饭");

         }

 

         public void jingShang(){

                  System.out.println("经商");

         }

}

class NorthPerson extends Person {

         public void eat(){

                  System.out.println("炖菜,吃面条");

         }

 

         public void yanJiu(){

                  System.out.println("学术");

         }

 

        

}

class DuoTaiTest2 {

         public static void main(String[] args){

                  //测试

                  //南方人

                  Person p = new SouthPerson();

                  p.eat();   

                  System.out.println("-------");

 

                  SouthPerson sp = (SouthPerson) p;

                  sp.eat();

                  sp.jingShang();

                  System.out.println("-------");

 

                  //北方人

                  p = new NorthPerson();

                  p.eat();

                  System.out.println("-------");

                  NorthPerson np = (NorthPerson) p;

                  np.eat();

                  np.yanJiu();

         }

}

 

3:抽象类与多态(掌握)

         把多个共性的东西(方法)提取到一个类中,这是继承的做法。

         但是呢,这多个共性的东西,在有些时候,方法声明一样,但是方法体在具体实现的时候内容不一样。

          所以,我们在定义这些共性的方法的时候,就不能给出具体的方法体, 而一个没有具体的方法体的方法是抽象的方法。

(1)    抽象类的概述:

         动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的。

         我们把一个不是具体的功能称为抽象的功能,如果一个类中有抽象的功能(方法),该类必须是抽象类。

(2)    格式格式:

abstract class 类名{}

public abstract void eat();

(3)抽象类的特点

A:抽象类和抽象方法必须用abstract关键字修饰

                  B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类。

                  C:抽象类不能实例化

                          因为它不是具体的。

                          抽象类是有构造方法的,但是不能实例化。那么,构造方法的作用是什么?

                          用于子类访问父类数据的构造化

                  D:抽象类的子类

                          1.是一个抽象类:如果不想重写抽象方法,该子类是一个抽象类。

                          2.是一个具体类:这个类必须重写抽象类中所有的抽象方法。

                  E:抽象类的实例化其实是以多态的方式,靠具体的子类实现的。

                          Animal a = new Cat();

 

例子:

//abstract class Animal ,抽象类的声明格式

abstract class Animal{            

//public abstract void eat(){}  //注意区分抽象方法(不能有主体)和空方法体

        

         public abstract void eat();//抽象方法

 

         public Animal(){}//抽象类是有构造方法的

}

 

//子类是抽象类

abstract class Dog extends Animal {}

//子类是具体类,重写抽象方法

class Cat extends Animal {

         public void eat(){

                  System.out.println("猫吃鱼");

         }

}

class AbstractDemo{

         public static void main(String[] args){

                  //创建对象

                  //Animal是抽象的;无法实例化

                  //Animal a = new Animal();

                  //抽象类可以通过多态(子类)的方式实例化

                  Animal a = new Cat();

                  a.eat();

         }

}

抽象类是不能通过构造方法实例化的,那么抽象类怎么实例化呢?

抽象类可以通过多态(子类)的方式实例化。

多态最主要的利用,不是在具体类之间使用。而是在抽象类之间使用!抽象类向外界提供的是一个个抽象的东西,而它的子类却是靠一个个具体的方法实现的(抽象类的子类必须重写抽象类中所有的抽象方法。)

 

(4)抽象类的成员特点:

A:成员变量

                  有变量,有常量

B:构造方法

                  有构造方法 。用于子类访问父类数据的初始化。

C:成员方法

                  既可以有抽象方法,也可以有非抽象方法。

抽象类的成员方法特性:

A:抽象方法,强制要求子类做的事情。

B:非抽象方法,子类继承的事情,提高代码复用性。

 

 

成员变量举例子:

abstract class Animal {

         //抽象类里面的成员变量,可以有常量有变量

         public int num = 10;//变量

         public final int num2 = 20;//常量

}

 

class Dog extends Animal {

 

class AbstractDemo2 {

         public static void main(String[] args){

                  //创建对象

                  Animal a = new Dog();

                  System.out.println(a.num);//10

                  a.num = 100;

                  System.out.println(a.num);//100

 

                  System.out.println(a.num2);

                  //a.num2 = 200;//错误: 无法为最终变量num2分配值

                  System.out.println(a.num2);

         }

}

                   

构造方法举例子:

 

abstract class Animal {

         public int num = 10;//变量

         public final int num2 = 20;//常量

 

         public Animal(){}//无参构造方法,用于子类访问父类数据的初始化。

 

         public Animal(String name,int age){} //有参构造方法,用于子类访问父类数据的初始化。

 

}

 

class Dog extends Animal {

 

class AbstractDemo2 {

         public static void main(String[] args){

                  Animal a = new Dog();

                  System.out.println(a.num);

                  System.out.println(a.num2);

         }

}

 

成员方法举例子:

abstract class Animal {

         //既可以有抽象方法,也可以有非抽象方法。

         public abstract void show();

 

         public void method(){

                  System.out.println("method");

         }

}

class Dog extends Animal {

         public void show(){

                  System.out.println("show Dog");

         }

 

 

class AbstractDemo2 {

         public static void main(String[] args){

                  //创建对象

                  Animal a = new Dog();

                  a.show();

                  a.method();

         }

}

                 

 

(5)抽象类的练习——猫狗案例练习

 

         猫狗案例

         具体事物:猫,狗

         共性:姓名,年龄,吃饭

 

         分析:从具体到抽象

                  猫:

                          成员变量:姓名,年龄

                          构造方法:无参,带参

                          成员方法:吃饭(猫吃鱼)

                  狗:

                          成员变量:姓名,年龄。

                          构造方法:无参,带参。

                          成员方法:吃饭(狗吃肉)

 

                  因为有共性的内容,所以就提取了一个父类。动物。

                  但是又由于吃饭的内容不一样,所以吃饭的方法是抽象的。

                  而方法是抽象的类,类就必须定义为抽象类。

 

                  抽象动物类:

                          成员变量:姓名,年龄。

                          构造方法:无参,带参。

                          成员方法:吃饭();

                 

 

         实现:从抽象到具体

                  动物类:

                          成员变量:姓名,年龄。

                          构造方法:无参,带参。

                          成员方法:吃饭();

                  狗类:

                          继承自动物类

                          重写吃饭();

                  猫类:

                          继承自动物类

                           重写吃饭();

                                           

 

abstract class Animal{

         //姓名

         private String name;

         //年龄

         private int age;

 

         public Animal(){}

 

         public Animal(String name ,int age){

                  this.name = name;

                  this.age = age;

         }

 

         public String getName(){

                  return name;

         }

 

         public void setName(String name){

                  this.name = name;

         }

        

         public int getAge(){

                  return age;

         }

 

         public void setAge(int age){

                  this.age = age;

         }

         //定义一个抽象方法

         public abstract void eat();

 

}

//定义具体的狗类

class Dog extends Animal{

         public Dog(){}

 

         public Dog(String name,int age){

                   super(name,age);

         }

 

         public void eat(){

                  System.out.println("狗吃肉");

         }

}

 

//定义具体的猫类

class Cat extends Animal{

         public Cat(){}

 

         public Cat(String name,int age){

                   super(name,age);

         }

 

         public void eat(){

                  System.out.println("猫吃鱼");

         }

}

 

//测试类

class AbstractTest {

         public static void main(String[] args){

                  //测试狗类

                  //具体类用法

                  //方式1:

                          Dog d = new Dog();

                          d.setName("旺财");

                          d.setAge(3);

                          System.out.println(d.getName()+"---"+d.getAge());

                          d.eat();

 

                  //方式2:

                          Dog d2 = new Dog("旺财",3);

                          System.out.println(d2.getName()+"----"+d.getAge());

                          d2.eat();

                          System.out.println("------------------------------");

        

                          Animal a = new Dog();

                          a.setName("旺财");

                          a.setAge(3);

                          System.out.println(a.getName()+"----"+a.getAge());

                          a.eat();

 

                          Animal a2 = new Dog("旺财",3);

                           

                          System.out.println(a.getName()+"----"+a.getAge());

                          a2.eat();

         }

}

 

(6)抽象类的几个小问题

                  A:抽象类有构造方法,不能实例化,那么构造方法有什么用?

                          用于子类访问父类数据的初始化

                  B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?

                          为了不让外界创建对象

                  C:abstract不能和哪些关键字共存

                          a:final      冲突

                          b:private 冲突

                          c:static 无意义

举例子:

  1. abstract和private冲突

 

abstract class Fu {

         //非法的修饰符组合: abstract和private

         //private只能被Fu类访问,private不能被继承就不能被子类重写,抽象方法要求被重写呢?

         private abstract void show();

}

 

class Zi extends Fu {

         public void show() {}

}

 

class AbstractDemo3 {

         public static void main(String[] args) {

         }

}

2. abstract和final冲突

 

同理

abstract class Fu {

         //错误: 非法的修饰符组合: abstract和final

         //final修饰的方法不能被子类重写

         final abstract void show();

}

 

class Zi extends Fu {

         public void show() {}

}

 

class AbstractDemo3 {

         public static void main(String[] args) {

                   

         }

}

3.static和abstract无意义

abstract class Fu {

         //错误: 非法的修饰符组合: abstract和static

         //static abstract void show();

         //静态方法可以通过类名.方法名()的格式访问,而抽象方法恰好是没有方法体的

         //访问一个没有方法体的方法,无意义

         public static void method(){

                  System.out.println("method");

         }

}

 

class Zi extends Fu {

         public void show() {}

}

 

class AbstractDemo3 {

         public static void main(String[] args) {

         //静态方法可以通过类名.方法名()的格式访问

                   Fu.method();

         }

}

4:接口与多态(掌握)

         (1)回顾猫狗案例,它们仅仅提供一些基本功能。

            比如:猫钻火圈,狗跳高等功能,不是动物本身就具备的,

            是在后面的培养中训练出来的,这种额外的功能定义到动物类中不适合,也不适合直接定义到猫、狗中。事物功能的扩展性,java提供了接口来定义这些额外功能。

(2)接口的特点:

A:接口用关键字interface表示  

                  interface 接口名{}

                  接口并不是实际意义上的一个类,仅仅表示功能的扩展。

 

B:类实现接口用implements表示

                  class  类名 implements 接口名{}

                 

C:接口不能实例化

                  那么,接口如何实例化呢?

                  按照多态的方式,由具体的子类来实例化。其实这也是多态的一种,接口多态。

                 

由此可见,多态:

                  A:具体类多态(几乎没有)

                  B:抽象类多态(常用)

                  C:接口多态(最常用)

D:接口的子类

                  要么是抽象类,但是意义不大。

                  要么(具体类)重写接口中的所有抽象方法(推荐方案)。

 

 举例子:

 //定义动物培训接口

 interface  AnimalTrain{

          public abstract void jump();

 }

 

//抽象类实现接口

 abstract class Dog implements AnimalTrain {

 }

 

 //具体类实现接口

 class Cat implements AnimalTrain {

          public void jump(){

                  System.out.println("猫可以跳高了");

          }

 }

 

 class InterfaceDemo {

          public static void main(String[] args){

                   //AnimalTrain是抽象的;无法实例化

                  //AnimalTrain at = new AnimalTrain();

                  //at.jump();

 

                  AnimalTrain at = new Cat();

                  at.jump();

          }

 }

(3)    接口的成员特点:

A.成员变量:只能是常量。默认修饰符public static final

B.构造方法:没有。因为接口主要是扩展功能的,而没有具体存在。

C.成员方法:只能是抽象方法,默认修饰符public abstract

        

举例子:

A.成员变量

                          接口中的变量默认只能是常量,并且是静态的。

                           默认修饰符:public static final

                          建议:自己手动给出public static final。

 

interface Inter {

         public int num = 10;

         public final int num2 = 20;

         public static final int num3 = 30;//建议自己手动给出

}

 

//“接口名+Impl”这种格式是接口的实现类格式

class InterImp1 implements Inter {

}

 

class InterfaceDemo2{

         public static void main(String[] args){

                  //创建对象

                  Inter i = new InterImp1();

                  System.out.println(i.num);

                  System.out.println(i.num2);

                  i.num = 100;// 错误: 无法为最终变量num分配值

                  i.num2 = 200;// 错误: 无法为最终变量num2分配值

                  System.out.println(i.num);

                  System.out.println(i.num2);

                  System.out.println("-----------");

System.out.println(Inter.num);

                  System.out.println(Inter.num2);

        

         }

}

                  B:构造方法

                          接口是没有构造方法的。

所有的类都默认继承自一个类:Object。类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。

举例子:

interface Inter {

         public static final int num3 = 30;

}

 

//“接口名+Impl”这种格式是接口的实现类格式

class InterImp1 implements Inter {

         public InterImp1(){

                  super();//疑问?

         }

}

疑问:如果接口没有构造方法,那么这里super()调用父类的无参构造方法怎么解释?

回答:所有的类都默认继承自一个类:Object。

所以,接口没有构造方法,不会影响子类访问父类super();

 

class InterImp1 extends Object implements Inter {

         public InterImp1(){

                  super();

         }

}

 

 

class InterfaceDemo2{

         public static void main(String[] args){

                  //创建对象

                  Inter i = new InterImp1();

                  System.out.println(Inter.num3);

         }

}

                  C:成员方法

                          接口中的方法只能是抽象方法(接口方法不能带有主体)。

                          默认修饰符:public abstract

                          建议:自己手动给出!

(4)类与类,类与接口,接口与接口

                  A:类与类

                          继承关系,只能单继承,可以多层继承

                  B:类与接口

                          实现关系,可以单实现,也可以多实现。

                          还可以在继承一个类的同时,实现多个接口

举例子:

interface Father {

         public abstract void show();

}

 

interface Mother {

         public abstract void show2();

}

 

class Son extends Object implements Father,Mother{

         public void show(){

                  System.out.println("show son");

         }

 

         public void show2(){

                  System.out.println("show2 son");

         }

}

class InterfaceDemo3 {

         public static void main(String[] args){

                  //创建对象

                  //实现了多个接口,记住对应的接口调用对应的方法

                  Father f = new Son();

                  f.show();

                  //f.show2();//报错

 

                  Mother m = new Son();

                  //m.show();//报错

                  m.show2();

         }

}

                  C:接口与接口

                          继承关系,可以单继承,也可以多继承

举例子:

interface Father {

         public abstract void show();

}

 

interface Mother {

         public abstract void show2();

}

interface Sister extends Father,Mother{

}

(5)抽象类和接口的区别(开发中意义不大,面试居多)?

                  A:成员区别

                          抽象类:

                                            成员变量:可以变量,也可以常量。

                                            构造方法:有。

                                            成员方法:可以抽象,也可以非抽象。

                          接口:

                                            成员变量:只可以常量。

                                            构造方法:无。

                                            成员方法:只可以抽象。

 

                  B:关系区别:

类与类

                          继承关系,只能单继承,可以多层继承

                    类与接口

                           实现关系,可以单实现,也可以多实现。

                          还可以在继承一个类的同时,实现多个接口

                    接口与接口

                          继承关系,可以单继承,也可以多继承

 

 

                  C:设计理念不同

                          抽象类:被继承体现的是“is a”的关系,抽象类中定义的是该继承体系的共性功能。

                          接口:被实现体现的是“like a”的关系,接口中定义的是该继承体系的扩展功能(类比 usb接口)。

         (6)3个案例:

猫狗案例、老师和学生案例、教练和运动员案例

                  A:猫狗案例,加入跳高功能

 

         猫狗案例,加入跳高的额外功能。

 

         分析:从具体到抽象。

                  猫:

                          姓名,年龄

                          吃饭,睡觉

                  狗:

                          姓名,年龄

                          吃饭,睡觉

                  由于有共性功能,所以,我们抽取出一个父类。

                  动物:

                          姓名,年龄

                          吃饭();//抽象方法

                          睡觉(){}//非抽象方法

                  猫:继承自动物

                  狗:继承自动物

 

                  调高的功能是一个新的扩展功能,所以我们要定义一个接口。

                  接口:

                          跳高。

                  部分猫:实现跳高。

                  部分狗:实现跳高。

 

         实现:

                  从抽象到具体。

        

         使用:

                  使用具体类

 

//定义跳高接口

interface Jumpping {

         //跳高功能

         public abstract void jump();

}

 

//定义抽象类

abstract class Animal {

         //姓名

         private String name;

         //年龄

         private int age;

 

         public Animal(){}

 

         public Animal(String name,int age){

                  this.name = name;

                  this.age = age;

         }

 

         public String getName(){

                  return name;

         }

 

         public void setName(String name){

                  this.name = name;

         }

 

         public int getAge(){

                  return age;

         }

 

         public void setAge(int age){

                  this.age = age;

         }

 

         //吃饭();

         public abstract void eat();

 

         //睡觉();

         public void sleep(){

                  System.out.println("睡觉觉了");

         }

}

 

// 具体猫类

class Cat extends Animal {

         public Cat(){

         }

 

         public Cat(String name,int age){

                  super(name,age);

         }

 

         public void eat(){

                  System.out.println("猫吃鱼");

         }

}

 

// 具体狗类

class Dog extends Animal {

         public Dog(){

         }

 

         public Dog(String name,int age){

                  super(name,age);

         }

 

         public void eat(){

                  System.out.println("狗吃肉");

         }

}

 

// 有跳高功能的猫

class JumpCat extends Cat implements Jumpping{

         public JumpCat(){}

 

         public JumpCat(String name,int age){

                  super(name,age);

         }

         public void jump(){

                  System.out.println("跳高猫");

         }

}

 

// 有跳高功能的狗

class JumpDog extends Dog implements Jumpping{

         public JumpDog(){}

 

         public JumpDog(String name,int age){

                  super(name,age);

         }

 

         public void jump(){

                  System.out.println("跳高狗");

         }

}

 

//定义跳高接口

class InterfaceTest {

         public static void main(String[] args){

                  //定义跳高猫

                  JumpCat jc = new JumpCat();

                  jc.setName("哆啦A梦");

                  jc.setAge(3);

                  System.out.println(jc.getName()+"-----"+jc.getAge());

                  jc.eat();

                  jc.sleep();

                  jc.jump();

                  System.out.println("--------------");

 

                  JumpCat jc2 = new JumpCat("加菲猫",2);

                  System.out.println(jc2.getName()+"-----"+jc2.getAge());

                  jc2.eat();

                  jc2.sleep();

                  jc2.jump();

         }

}

                  B:老师和学生案例,加入抽烟功能

 

         老师和学生案例,加入抽烟的额外功能

 

         分析:从具体到抽象

                  老师:姓名,年龄,吃饭,睡觉

                  学生:姓名,年龄,吃饭,睡觉

 

                  由于有共性功能,我们提取出一个父类,人类。

 

                  人类:

                          姓名,年龄

                          吃饭();//抽象,空语句

                          睡觉(){}//具体

 

                  抽烟的额外功能不是人或者老师,或者学生一开始就应该具备的。所以,我们把它定义为接口

                 

                  抽烟接口。

 

                  部分老师抽烟:实现抽烟接口。

                  部分学生抽烟:实现抽烟接口。

        

         实现:从抽象到具体。

 

         使用:具体。

 

//定义抽烟接口

interface Smoking {

         //抽烟的抽象方法

         public abstract void smoke();

}

 

//定义抽象人类

abstract class Person {

         //姓名

         private String name;

         //年龄

         private int age;

 

         public Person(){}

 

         public Person(String name,int age){

                  this.name = name;

                  this.age = age;

         }

 

         public String getName(){

                  return name;

         }

 

         public void setName(String name){

                  this.name = name;

         }

 

         public int getAge(){

                  return age;

         }

 

         public void setAge(int age){

                  this.age = age;

         }

 

         //吃饭();

         public abstract void eat();

        

         //睡觉(){}

         public void sleep() {

                  System.out.println("睡觉觉了");

         }

}

 

//具体老师类

class Teacher extends Person {

         public Teacher(){}

 

         public Teacher(String name,int age){

                  super(name,age);

         }

 

         public void eat(){

                  System.out.println("开水煮白菜");

         }

}

 

//具体学生类

class Student extends Person {

         public Student(){}

 

         public Student(String name,int age){

                  super(name,age);

         }

 

         public void eat(){

                  System.out.println("吃红烧肉");

         }

}

//抽烟的老师

class SmokingTeacher extends Teacher implements Smoking{

         public SmokingTeacher(){}

 

         public SmokingTeacher(String name,int age){

                  super(name,age);

         }

 

         public void smoke(){

                  System.out.println("抽烟的老师");

         };

}

//抽烟的学生

class SmokingStudent extends Student implements Smoking{

         public SmokingStudent(){}

 

         public SmokingStudent(String name,int age){

                  super(name,age);

         }

 

         public void smoke(){

                  System.out.println("抽烟的学生");

         };

}

 

class InterfaceTest2 {

         public static void main(String[] args){

                  //测试学生

                  SmokingStudent ss = new SmokingStudent();

                  ss.setName("刘德华");

                  ss.setAge(27);

                  System.out.println(ss.getName()+"----"+ss.getAge());

                  ss.eat();

                  ss.sleep();

                  ss.smoke();

                  System.out.println("-------------");

 

                  SmokingStudent ss2 = new SmokingStudent("梁朝伟",32);

                  System.out.println(ss2.getName()+"----"+ss2.getAge());

                  ss2.eat();

                  ss2.sleep();

                  ss2.smoke();

         }

}

 

C教练和运动员案例(类、抽象类、接口的综合小案例)

 

         2018年7月1日10:52:57

         教练和运动员案例(学生分析然后讲解)

         乒乓球运动员和篮球运动员

         乒乓球教练和篮球教练

         为了出国交流,跟乒乓球相关的人员都需要学习英语

         请运用所学的知识:

         分析,这个案例中有哪些抽象类,哪些接口,哪些具体类

 

          整个分析过程,我是通过画图讲解的。

 

 

//定义一个说英语的接口

interface SpeakEnglish {

         //说英语

         public abstract void speak();

}

 

//定义人的抽象类

abstract class Person {

         private String name;

         private int age;

 

         public Person(){}

 

         public Person(String name,int age){

                  this.name = name;

                  this.age = age;

         }

 

         public String getName(){

                  return name;

         }

 

         public void setName(String name){

                  this.name = name;

         }

 

         public int getAge(){

                  return age;

         }

 

         public void setAge(int age){

                  this.age = age;

         }

          

          //睡觉

         public void sleep(){

                  System.out.println("人都是要睡觉的");

         }

         //吃饭

         public abstract void eat();

}

 

//定义运动员抽象类

abstract class Player extends Person {

         public Player(){}

 

         public Player(String name,int age){

                  super(name,age);  

         }

 

         //学习

         public abstract void study();

}

 

//定义教练抽象类

abstract class Coach extends Person {

         public Coach(){}

 

         public Coach(String name,int age){

                  super(name,age);  

         }

 

         //教

         public abstract void teach();

}

//定义乒乓球运动员具体类

class PingPangPlayer extends Player implements SpeakEnglish {

         public PingPangPlayer(){}

 

         public PingPangPlayer(String name,int age){

                   super(name,age);

         }

 

         //吃

         public void eat(){

                  System.out.println("乒乓球运动员吃大白菜,喝小米粥");

         }

 

         //学习

         public void study(){

                  System.out.println("乒乓球运动员学习如何发球和接球");

         }

         //说英语

         public void speak(){

                  System.out.println("乒乓球运动员说英语");

         }

}

 

//定义篮球运动员具体类

class BasketballPlayer extends Player {

         public BasketballPlayer(){}

 

         public BasketballPlayer(String name,int age){

                   super(name,age);

         }

 

         //吃

         public void eat(){

                  System.out.println("篮球运动员吃牛肉,喝牛奶");

         }

 

         //学习

         public void study(){

                  System.out.println("篮球运动员学习如何运球和投篮");

         }

}

 

//定义乒乓球教练具体类

class PingPangCoach extends Coach implements SpeakEnglish {

         public PingPangCoach(){}

 

         public PingPangCoach(String name,int age){

                   super(name,age);

         }

 

         //吃

         public void eat(){

                  System.out.println("乒乓球教练吃小白菜,喝大米粥");

         }

 

         //教

         public void teach(){

                  System.out.println("乒乓球教练教如何发球和接球");

         }

         //说英语

         public void speak(){

                  System.out.println("乒乓球教练说英语");

         }

}

 

//定义篮球教练具体类

class BasketballCoach extends Coach {

         public BasketballCoach(){}

 

         public BasketballCoach(String name,int age){

                   super(name,age);

         }

 

         //吃

         public void eat(){

                  System.out.println("篮球教练吃羊肉,喝羊奶");

         }

 

         //教

         public void teach(){

                  System.out.println("篮球教练教如何运球和投篮");

         }

 

}

 

class InterfaceDemo {

         public static void main(String[] args){

                  //测试运动员(乒乓球运动员和篮球运动员)

                  PingPangPlayer ppp = new PingPangPlayer();

                  ppp.setName("王浩");

                  ppp.setAge(33);

                  System.out.println(ppp.getName()+"----"+ppp.getAge());

                  ppp.eat();

                  ppp.study();

                  ppp.speak();

                  ppp.sleep();

                  //通过带参构造给数据

                  PingPangPlayer ppp2 = new PingPangPlayer("王浩",33);

                  System.out.println(ppp2.getName()+"----"+ppp2.getAge());

                  ppp2.eat();

                  ppp2.study();

                  ppp2.speak();

                  ppp2.sleep();

 

 

                  //篮球运动员

                  BasketballPlayer bp = new BasketballPlayer();

                  bp.setName("姚明");

                  bp.setAge(34);

                  System.out.println(bp.getName()+"----"+bp.getAge());

                  bp.eat();

                  bp.study();

                  //bp.speak();//没有该方法

                  bp.sleep();

                  //通过带参构造给数据

                  BasketballPlayer bp2 = new BasketballPlayer("姚明",34);

                  System.out.println(bp2.getName()+"----"+bp2.getAge());

                  bp2.eat();

                  bp2.study();

                  //bp2.speak();//没有该方法

                  bp2.sleep();

                   

         }

}

5:形式参数和返回值的问题(理解)

(1)形式参数:

                  基本类型(太简单,不是我今天要讲解的)

                  引用类型

                          类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象。

                          抽象类:需要的是该抽象类的子类对象。

                                   接口:需要的是该接口的实现类对象。

a.类名:需要该类的对象

class Student {

         public void study(){

                  System.out.println("Good Good Study,Day Day Up");

         }

}

 

class StudentDemo {

         public void method(Student s){//将ss赋给s,ss = new

                  // Student(); Student s = new Student();

                  s.study();

         }

}

class StudentTest {

         public static void main(String[] args){

                  //需求:我要测试学生类的study方法

                  Student s = new Student();

                  s.study();

                  System.out.println("-----------");

 

                  //需求2:我要测试StudentDemo类中的method()方法

                  StudentDemo sd = new StudentDemo();

                  Student ss = new Student();

                  sd.method(ss);

       

                  // 匿名对象用法

            new StudentDemo().method(new Student());

         }

}

b.抽象类名:需要的是该抽象类的子类对象

举例子:

abstract class Person {

         public abstract void study();

}

 

class PersonDemo {

         //抽象类调用方法,肯定是用子类去实现的

         public void method(Person p){//p; p = new Student(); Person p = new Student();//多态

                  p.study();

         }

//定义一个具体的学生类

class Student extends Person {

         public void study(){

                  System.out.println("Good Good Study,Day Day Up");

         }

}

class PersonTest {

         public static void main(String[] args){

                  //目前是没有办法使用的

                  //因为抽象类没有对应的具体类

                  //那么,我们就应该先定义一个具体类

                  //需求:我要使用PersonDemo类中的method()方法

                  PersonDemo pd = new PersonDemo();

                  Person p = new Student();

                  pd.method(p);

 

         }

}

c.接口名:需要该接口的实现类对象

举例子:

//定义一个爱好的接口

interface Love {

         public abstract void love();

}

 

class LoveDemo {

         public void method(Love l){//l; l = new Teacher(); Love l = new Teacher(); 多态

                  l.love();

         }

}

 

//定义具体类实现接口

class Teacher implements Love {

         public void love(){

                  System.out.println("老师爱学生,爱java,爱林青霞");

         }

}

class TeacherTest {

         public static void main(String[] args){

                  //需求:我要测试LoveDemo类中的love()方法

                  LoveDemo ld = new LoveDemo();

                  Love l = new Teacher();

                  ld.method(l);

         }

}

(2)返回值类型:

基本类型:(基本类型太简单,不准备讲解)

引用类型:

                          类:返回的是该类的对象。

                          抽象类:返回的是该抽象类的子类对象。

                              接口:返回的是该接口的实现类的对象

         a.类名:返回的是该类的对象

举例子:返回值类型是一个类名,真正返回的是该类的对象。

class Student {

         public void study(){

                  System.out.println("Good Good Study,Day Day Up");

         }

}

 

class StudentDemo {

         public Student getStudent(){

                  //Student s = new Student();

                  //Student ss = s;

 

                  //Student s = new Student();

                  //return s;

                  return new Student();

         }

}

class StudentTest2 {

         public static void main(String[] args){

                  //需求:我要使用Student类中的study()方法

                  //但是,这一次我的要求是,不要直接创建Student的对象

                  //让你使用StudentDemo帮你创建对象

                  StudentDemo sd = new StudentDemo();

                  Student s = sd.getStudent();//new Student();Student s = new Student();

                  s.study();

                 

         }

}

b.抽象类名:返回的是该抽象类的子类对象

举例子:

abstract class Person {

         public abstract void study();

}

 

class PersonDemo {

         public Person getPerson(){

                  //return new Person;//Person是一个抽象类

                  return new Student();

         }

}

 

class Student extends Person {

         public void study(){

                  System.out.println("Good Good Study,Day Day Up");

         }

}

class PersonTest2 {

         public static void main(String[] args){

                  //需求:我要测试Person类中的study()方向

                  PersonDemo pd = new PersonDemo();

                  Person p = pd.getPerson();//Person p = new Student();多态

                  p.study();

         }

}

c.接口名:返回的是该接口的实现类的对象

举例子:

//定义一个爱好的接口

interface Love {

         public abstract void love();

}

 

class LoveDemo {

         public Love getLove(){

                  //Love l = new Teacher();

                  //return l;

 

                  return new Teacher();

         }

}

 

//定义具体类实现接口

class Teacher implements Love {

         public void love(){

                  System.out.println("老师爱学生,爱java,爱林青霞");

         }

}

class TeacherTest2 {

         public static void main(String[] args){

                  //如何测试呢?

                  LoveDemo ld = new LoveDemo();

                  Love l = ld.getLove();// Love l = new Teacher();多态

                  l.love();

         }

}

(3)链式编程

                  对象.方法1().方法2().......方法n();

每次调用完方法后,返回的是一个对象。

 

                 

                  这种用法:其实在方法1()调用完毕后,应该一个对象;

                                方法2()调用完毕后,应该返回一个对象。

                                     方法n()调用完毕后,可能是对象,也可以不是对象。

举例子:

 

class Student {

         public void study(){

                  System.out.println("Good Good Study,Day Day Up");

         }

}

 

class StudentDemo {

         public Student getStudent(){

                  return new Student();

         }

}

 

class StudentTest3 {

         public static void main(String[] args){

                  //如何调用的呢?

                  StudentDemo sd = new StudentDemo();

                  //Student s = sd.getStudent();

                  //s.study();

 

                  //大家注意了,链式编程

                  sd.getStudent().study();

         }

}

6:包(理解)

         (1):其实就是文件夹

         (2):作用

                          A:把相同的类名放到不同的包中(区分同名的类)

                          B:对类进行分类管理(重点)

                                                     a:按照功能分

                                                    b:按照模块分

 

         举例:

                  老师类:增加、删除、修改、查询

                  学生类:增加、删除、修改、查询

                  ......

 

                  方案1:按照功能分

                          cn.itcast.add

                              AddStudent

                              AddTeacher

                          cn.itcast.delete

                              DeleteStudent

                              DeleteTeacher

                          cn.itcast.update

                              UpdateStudent

                              UpdateTeacher

                          cn.itcast.find

                              FindStudent

                              FindTeacher

                 

                  方案2:按照模块分

                          cn.itcast.teacher

                              AddTeacher

                              DeleteTeacher

                              UpdateTeacher

                              FindTeacher

                          cn.itcast.student

                              AddStudent

                              DeleteStudent

                              UpdateStudent

                              FindStudent

         (3)包的定义(掌握):

                  Package 包名;

                          多级包用.分开即可

        

         (4)注意事项(掌握):

                  A:package语句必须是程序的第一条可执行的代码

                  B:package语句在一个java文件中只能有一个

                  C:如果没有package,默认表示无包名。

 

 

 

 

         带包的编译和运行:

                  A: 手动式

                          a:编写一个带包的java文件(HelloWorld.java)

package cn.itcast;

 

class HelloWorld {

         public static void main(String[] args){

                  System.out.println("HelloWorld");

         }

}

                          b:通过javac命令编译该java文件

                          c:手动创建包名。

                                   cn/itcast

                          c:把b步骤的class文件放到(剪切)c步骤的最底层包。

                          e:回到和包根目录在同一目录的地方,然后带包运行。

                                   java cn.itcast.HelloWorld

                  B:自动式(掌握)

                          a:编写一个带包的java文件。

                          b:javac编译的时候带上-d即可

                                   java –d . HelloWorld.java

                          C:回到和包根目录在同一目录的地方,然后带包运行。

                                   java cn.itcast.HelloWorld

 

7:导包(掌握)

         (1)不同包下的类之间的访问,我们发现,每次使用不同包下的类的时候,都需要加包的全路径。比较麻烦。这个时候,java就提供了导包的功能。

 

(1)    导包

格式:import 包名...类名; 这种方式是导入到类的级别。

                  另一种:

                          import 包名...*;(不建议)

                  注意:用到哪个类就导哪个类

         (3)package,import,class的顺序关系

                  package > import > class(package在最前面)

Package:只能有一个

import:可以有多个

class:可以有多个,以后建议是一个。

        

8:权限修饰符(掌握)

(1)权限修饰符

                   

 

本类

同一个包下(子类和无关类)

不同包下的子类

不同包下的无关类

private

Y

 

 

 

默认

Y

Y

 

 

protected

Y

Y

Y

 

public

Y

Y

Y

Y

 

(2)这四种权限修饰符在任意时刻只能出现一种。

                  public class Demo {}               

 

(3):常见的修饰符(理解)

         (1)分类:

                  权限修饰符:private,默认修饰符,protected,public

                  状态修饰符:static,final

                  抽象修饰符:abstract

         (2)常见修饰符的使用(不用记)

         类:

                  权限修饰符:默认修饰符,public

                  状态修饰符:final

                  抽象修饰符:abstract

 

                  用的最多的就是:public

        

         成员变量:

                  权限修饰符:private,默认的,protected,public

                  权限修饰符:static,final

 

                  用的最多的就是:private

        

         构造方法:

                  权限修饰符:private,默认的,protected,public

                  构造方法只能使用权限修饰符修饰

                  用的最多的就是:public

 

         成员方法:

                  权限修饰符:private,默认的,protected,public

                  状态修饰符:static,final

                  抽象修饰符:abstract

用的最多的就是:public

 

要会自己测试!

    1

    2

    3

    4

    5

    6

    7

    8

    9

   10

   11

   12

   13

   14

   15

   16

   17

   18

   19

   20

   21

   22

   23

   24

   25

   26

   27

   28

   29

   30

   31

   32

   33

   34

   35

   36

   37

public class Demo {

        //成员变量

        private int x = 10;

        int y = 20;

        protected int z = 30;

        public int a = 40;

        public final int b = 50;

        public final int c = 60;

        public static final int d = 70;

        //错误: 此处不允许使用修饰符abstract

        //abstract int e = 80;

 

        //构造方法

        private Demo(){}

 

        Demo(String name){}

 

        protected Demo(String name,int age){}

 

        public Demo(String name,int age,String address){}

 

        //构造方法只能使用权限修饰符修饰:private,默认的,protected,public

        

        //错误: 此处不允许使用修饰符static

        //public static Demo(){}

        //错误: 此处不允许使用修饰符final

        //public final Demo(){}

        //错误: 此处不允许使用修饰符abstract

        //public abstract Demo(){}

 

        //成员方法

        //static void show(){}

        //abstract void show();

        //final void show(){}

 

}

 

 

 

 (3)另外比较常见的:

          

                  成员变量:public static final

public static final int X = 10;

 

                  成员方法:public static

                                     public abstract

                                     public final 

                  public static void show() {}

                  public final void show() {}

                  public abstract void show();

 

9:内部类(理解)

      (1)内部类概述:

把类定义在其他类的内部,这个类就被称为内部类。

                  举例:把类B定义在类A中,类B就被称为内部类。

      (2)内部类的访问规则

                  A:可以直接访问外部类的成员,包括私有

                  B:外部类要想访问内部类成员,必须创建对象

举例子:

class Outer {

         private int num = 10;

 

         class Inner {

                  public void show(){

                          System.out.println(num);

                  }

         }

 

         public void method(){

                  //找不到符号

                  //show();

 

                  Inner i = new Inner();

                  i.show();

         }

}

class InnerClassDemo {

         public static void main(String[] args){

         }

}

      (3)内部类的分类

         内部类分为成员内部类和局部内部类

 

         根据内部类的位置

                  成员位置:在成员位置定义的类,被称为成员内部类。

                  局部位置:在局部位置定义的类,被称为局部内部类。

 

举例子:

 

class Outer {

         private int num = 10;

 

         //成员位置

         class Inner {

 

         }

 

         public void method(){

                  //局部位置

                  class Inner {

 

                  }

         }

}

class InnerClassDemo2 {

         public static void main(String[] args){

         }

}

(4)成员内部类的调用

         成员内部类:在成员位置定义的类,被称为成员内部类。

 

         如何直接访问成员内部类的成员。

                  格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;

举例子:

class Outer {

         private int num = 10;

 

         class Inner {

                  public void show(){

                          System.out.println(num);

                  }

         }

}

class InnerClassDemo3 {

         public static void main(String[] args){

                  //需求:我要访问Inner类的show()方法

                  //Inner i = new Inner();

                  //i.show();

                  //格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;

                  Outer.Inner oi = new Outer().new Inner();

                  oi.show();

         }

}

 

      (5)成员内部类的常见修饰符

                  A:private 为了保证数据的安全性

B:static 为了访问的方便性

         注意:静态内部类访问的外部类数据,外部类数据必须用静态类修饰

                    也就是说被静态修饰的成员内部类只能访问外部类的静态成员

 

 

案例:关于private,我有一个人(人有身体,身体内有心脏)

                  class Body{

                          class Heart{

                                   public void operator(){

                                            System.out.println("心脏搭桥");

                                   }

                          }

                  }

                  按照我们刚才的讲解,来使用一下

                  Body.Heart bh = new Body().new Heart();

                  bh.operator();

                  在实际开发中,一般内部类是不让外界直接访问的。

                  //加了private后,就不能被外界访问了,那么,怎么玩呢?

 由外部类Body提供一个方法method()

                  class Body{

                          private class Heart{

                                   public void operator(){

                                            System.out.println("心脏搭桥");

                                   }

                          }

 

                          public void method(){

                                   if(如果你是外科医生){

                                            Heart h = new Heart();

                                            h.operator();

                                   }

                          }

                  }

                  Body b = new Body();

                  b.method();

 

B:static 为了访问的方便性

                 

                  成员内部类不是静态的:

                          外部类名.内部类名 对象名 = new 外部类名.new 内部类名();

                  成员内部类是静态的:

                          外部类名.内部类名 对象名 = new 外部类名.内部类名();

举例子:

class Outer {

    private int num = 10;

         private static int num2 = 100;

 

         //静态不能修饰类(外部类)

    //内部类用静态修饰是因为内部类可以看成是外部类的成员

    public static class Inner {

        public void show() {

                          //System.out.println(num);

                          //注意:静态内部类访问的外部类数据必须用静态修饰。

            System.out.println(num2);

        }

 

        public static void show2() {

                          //System.out.println(num);

            System.out.println(num2);

        }

    }

}

class InnerClassDemo4 {

    public static void main(String[] args) {

                  //使用内部类

                  //错误: 限定的新静态类

                  //Outer.Inner oi = new Outer().new Inner();

                  //oi.show();

                  //oi.show2();

 

                  //成员内部类被静态修饰后的访问方式是:

                  //格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();

                  Outer.Inner oi = new Outer.Inner();

                  oi.show();

                  oi.show2();

 

                  //show2()的另一种调用方式

                  Outer.Inner.show2();

    }

}

      (6)成员内部类的面试题

 

         面试题:

                   补齐代码,在控制台分别输出30,20,10。

class Outer {

         public int num = 10;

         class Inner {

                  public int num = 20;

                  public void show(){

                          int num = 30;

                          System.out.println(?);

                          System.out.println(??);

                          System.out.println(???);

                  }

         }

}

 

 

         注意:

                  1.内部类和外部类没有继承关系。

                  2.通过外部类名限定this对象——Outer.this

 

class Outer {

         public int num = 10;

         class Inner {

                  public int num =20;

                  public void show(){

                          int num = 30;

                          System.out.println(num);

                          System.out.println(this.num);

                          //System.out.println(new Outer().num);

                          System.out.println(Outer.this.num);// new Outer().num也行

                  }

         }

}

 

class InnerClassTest {

         public static void main(String[] args){

                  Outer.Inner oi = new Outer().new Inner();

                  oi.show();

         }

}

      (7)局部内部类

                  A:可以直接访问外部类的成员

                  B:在局部位置,可以创建内部类对象。通过对象调用内部类方法,来使用局部内部类功能。

举例子:

class Outer {

          private int num = 10;

          public void method(){

                   

                   class Inner {

                           public void show(){

                                    //可以直接访问外部类的成员

                                   System.out.println(num);      

                           }

                   }

                   //在局部位置,可以创建内部类对象。通过对象调用内部类方法,来使用局部内部类功能。

                   Inner i = new Inner();

                   i.show();

          }

}

 

class Test {

         public static void main(String[] args){

                  Outer o = new Outer();

                  o.method();//10

         }

 

}

局部内部类访问局部变量的注意事项?

                  A:局部内部类访问局部变量,局部变量必须加final修饰。

                  B:为什么呢?

                          因为局部变量使用完毕就消失,而堆内存的数据(对象)并不会立即消失。

                          所以,堆内存还是用该变量,而改变量已经没有了。

                          为了让该值还存在,就加final修饰。

                          通过反编译工具我们看到了,加入final修饰后,这个变量就变成了常量。堆内存直接存储的是数值,而不是变量名。

举例子:

class Outer {

          private int num = 10;

 

          public void method(){

                   final int num2 = 20;//此处必须加final不然会报错 

                   class Inner {

                           public void show(){

                                   System.out.println(num);

                                   //错误: 从内部类中访问本地变量num2; 需要被声明为最终类型

                                   System.out.println(num2);

                           }

                   }

 

                   Inner i = new Inner();

                   i.show();

          }

}

class InnerClassDemo {

         public static void main(String[] args){

                  Outer o = new Outer();

                  o.method();

         }

}

      (8)匿名内部类(掌握)

                  A:其实就是局部内部类的简化形式

                  B:前提

                          存在一个类或者接口。

                          这里的类可以是具体类也可以是抽象类。

                  C:格式:

                          new 类名或者接口名() {

                                   重写方法;

                          }

                  D:本质是什么呢?

                          其实是一个继承了该类或者实现了该接口的子类匿名对象

                          匿名内部类的本质是继承类或者实现了接口的子类匿名对象     

举例子:

interface Inter {

         public abstract void show();

}

 

class Outer {

         public void method(){

                  //方法1

                   new Inter(){

                           public void show(){

                                   System.out.println("show");

                           }

                   }.show();

                  //方法2

         Inter i = new Inter(){//多态

                          public void show(){

                                   System.out.println("show");

                          }

                  };

 

                  i.show();

         }

}

class InnerClassDemo6 {

         public static void main(String[] args){

                  Outer o = new Outer();

                  o.method();

         }

}

程序结果:打印show

      (9)匿名内部类在开发中的使用

                  我们在开发的时候,会看到抽象类,或者接口作为参数。

                  而这个时候,我们知道实际需要的是一个子类对象。

                  如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。

举例子:

interface Person {

         public abstract void study();

}

 

class PersonDemo {

         //接口名作为形式参数

         //其实这里需要的不是接口,而是该接口的实现类的对象。

         public void method(Person p){

                  p.study();

         }

}

 

//实现类

class Student implements Person {

         public void study(){

                  System.out.println("Good Good Study,Day Day Up");

         }

}

class  InnerClassTest2{

         public static void main(String[] args){

                  //测试1(容易理解):接口名作为形式参数

                  PersonDemo pd = new PersonDemo();

                  Person p = new Student();

                  pd.method(p);// Good Good Study,Day Day Up

                  System.out.println("----------");

 

                  //测试2(代码简洁):匿名内部类在开发中的使用

//不必像方法1,还要做个接口的实现类Student

                  //匿名内部类的本质是继承类或者实现了接口的子类匿名对象 

                  pd.method(new Person(){

                          public void study(){

                                   System.out.println("好好学习,天天向上");

                          }

                  });

         }

}               

 

注意:以上代码如果使用匿名内部类实现是不需要Student类的。

      (10)匿名内部类的面试题(补齐代码)

要求补齐代码,输出HelloWorld

interface Inter{ void show();}

 

class Outer{ //补齐代码}

class OuterDemo{

         public static void main(String[] args){

                  Outer.method().show();

         }

}

 

实现:

interface Inter{

         void show();

         //默认修饰符public abstract

}

 

class Outer {//补齐代码

         public static Inter method(){

                  //子类对象--子类匿名对象

                  return new Inter(){

                          public void show(){

                                   System.out.println("HelloWorld");

                          }

                  };

         }

}

 

class InnerClassTest3 {

         public static void main(String[] args){

                  Outer.method().show();//链式编程

                  /*

                          1:Outer.method()可以看出method()应该是Outer中的一个静态方法

                          2:Outer.method().show()可以看出method()方法的返回值是一个对象。

                  又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型

                  是一个接口。

*/

         }

}

转载于:https://www.cnblogs.com/weihua0624/p/9307288.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值