Java笔记(10):面向对象--内部类

Posted 花醉红尘

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java笔记(10):面向对象--内部类相关的知识,希望对你有一定的参考价值。

1、类名作为形式参数

 1 /*
 2     形式参数:
 3         基本类型
 4         引用类型
 5             类名:(匿名对象的时候其实我们已经讲过了) 需要的是该类的对象
 6             抽象类:
 7             接口
 8 */
 9 class Student {
10     public void study() {
11         System.out.println("Good Good Study,Day Day Up");
12     }
13 }
14 
15 class StudentDemo {
16     public void method(Student s) { //ss; ss = new Student();  Student s = new Student();
17         s.study();
18     }
19 }
20 
21 class StudentTest {
22     public static void main(String[] args) {
23         //需求:我要测试Student类的study()方法
24         Student s = new Student();
25         s.study();
26         System.out.println("----------------");
27         
28         //需求2:我要测试StudentDemo类中的method()方法
29         StudentDemo sd = new StudentDemo();
30         Student ss = new Student();
31         sd.method(ss);
32         System.out.println("----------------");
33         
34         //匿名对象用法
35         new StudentDemo().method(new Student());
36     }
37 }

2、抽象类名作为形式参数

 1 /*
 2     形式参数:
 3         基本类型
 4         引用类型
 5             类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
 6             抽象类:需要的是该抽象的类子类对象
 7             接口
 8 */
 9 abstract class Person {
10     public abstract void study();
11 }
12 
13 class PersonDemo {
14     public void method(Person p) {//p; p = new Student();  Person p = new Student(); //多态
15         p.study();
16     }
17 }
18 
19 //定义一个具体的学生类
20 class Student extends Person {
21     public void study() {
22         System.out.println("Good Good Study,Day Day Up");
23     }
24 }
25 
26 class PersonTest {
27     public static void main(String[] args) {
28         PersonDemo pd = new PersonDemo();
29         Person p = new Student();
30         pd.method(p);
31     }
32 }

3、接口名作为形式参数

 1 /*
 2     形式参数:
 3         基本类型(太简单,不是我今天要讲解的)
 4         引用类型
 5             类名:(匿名对象的时候其实我们已经讲过了)需要的是该类的对象
 6             抽象类:需要的是该抽象的类子类对象
 7             接口:需要的是该接口的实现类对象
 8 */
 9 //定义一个爱好的接口
10 interface Love {
11     public abstract void love();
12 }
13 
14 class LoveDemo {
15     public void method(Love l) { //l; l = new Teacher();  Love l = new Teacher(); 多态
16         l.love();
17     }
18 }
19 
20 //定义具体类实现接口
21 class Teacher implements Love {
22     public void love() {
23         System.out.println("老师爱学生,爱Java,爱林青霞");
24     }
25 }
26 
27 class TeacherTest {
28     public static void main(String[] args) {
29         //需求:我要测试LoveDemo类中的love()方法
30         LoveDemo ld = new LoveDemo();
31         Love l = new Teacher();
32         ld.method(l);
33     }
34 }

 4、类名作为返回值类型

 1 /*
 2     返回值类型
 3         基本类型:(基本类型太简单,我不准备讲解)
 4         引用类型:
 5             类:返回的是该类的对象
 6             抽象类:
 7             接口:
 8 */
 9 class Student {
10     public void study() {
11         System.out.println("Good Good Study,Day Day Up");
12     }
13 }
14 
15 class StudentDemo {
16     public Student getStudent() {
17         //Student s = new Student();
18         //Student ss = s;
19         
20         //Student s = new Student();
21         //return s;
22         return new Student();
23     }
24 }
25 
26 class StudentTest2 {
27     public static void main(String[] args) {
28         //需求:我要使用Student类中的study()方法
29         //但是,这一次我的要求是,不要直接创建Student的对象
30         //让你使用StudentDemo帮你创建对象
31         StudentDemo sd = new StudentDemo();
32         Student s = sd.getStudent(); //new Student(); Student s = new Student();
33         s.study();
34     }
35 }

5、抽象类名作为返回值类型

 1 /*
 2     返回值类型
 3         基本类型:(基本类型太简单,我不准备讲解)
 4         引用类型:
 5             类:返回的是该类的对象
 6             抽象类:返回的是该抽象类的子类对象
 7             接口:
 8 */
 9 abstract class Person {
10     public abstract void study();
11 }
12 
13 class PersonDemo {
14     public Person getPerson() {
15         //Person p = new Student();
16         //return p;
17         
18         return new Student();
19     }
20 }
21 
22 class Student extends Person {
23     public void study() {
24         System.out.println("Good Good Study,Day Day Up");
25     }
26 }
27 
28 class PersonTest2 {
29     public static void main(String[] args) {
30         //需求:我要测试Person类中的study()方法
31         PersonDemo pd = new PersonDemo();
32         Person p = pd.getPerson(); //new Student();  Person p = new Student(); 多态
33         p.study();
34     }
35 }

6、接口名作为返回值类型

 1 /*
 2     返回值类型
 3         基本类型:(基本类型太简单,我不准备讲解)
 4         引用类型:
 5             类:返回的是该类的对象
 6             抽象类:返回的是该抽象类的子类对象
 7             接口:返回的是该接口的实现类的对象
 8 */
 9 //定义一个爱好的接口
10 interface Love {
11     public abstract void love();
12 }
13 
14 class LoveDemo {
15     public Love getLove() {
16         //Love l = new Teacher();
17         //return l;
18         
19         return new Teacher();
20     }
21 }
22 
23 //定义具体类实现接口
24 class Teacher implements Love {
25     public void love() {
26         System.out.println("老师爱学生,爱Java,爱林青霞");
27     }
28 }
29 
30 class TeacherTest2 {
31     public static void main(String[] args) {
32         //如何测试呢?
33         LoveDemo ld = new LoveDemo();
34         Love l = ld.getLove(); //new Teacher(); Love l = new Teacher(); 多态
35         l.love();
36     }
37 }

7、链式编程

 1 /*
 2     链式编程。
 3         每次调用完毕方法后,返回的是一个对象。
 4 */
 5 class Student {
 6     public void study() {
 7         System.out.println("Good Good Study,Day Day Up");
 8     }
 9 }
10 
11 class StudentDemo {
12     public Student getStudent() {
13         return new Student();
14     }
15 }
16 
17 class StudentTest3 {
18     public static void main(String[] args) {
19         //如何调用的呢?
20         StudentDemo sd = new StudentDemo();
21         //Student s = sd.getStudent();
22         //s.study();
23         
24         //大家注意了
25         sd.getStudent().study();
26     }
27 }

8、包的概述及编译运行

 1 /*
 2     包:
 3         A:其实就是文件夹
 4         B:作用
 5             a:把相同的类名放到不同的包中
 6             b:对类进行分类管理
 7             
 8     举例:
 9         学生:增加,删除,修改,查询
10         老师:增加,删除,修改,查询
11         ...
12         
13         方案1:按照功能分
14             cn.itcast.add
15                 AddStudent
16                 AddTeacher
17             cn.itcast.delete
18                 DeleteStudent
19                 DeleteTeacher
20             cn.itcast.update
21                 UpdateStudent
22                 UpdateTeacher
23             cn.itcast.find
24                 FindStudent
25                 FindTeacher
26         
27         方案2:按照模块分
28             cn.itcast.teacher
29                 AddTeacher
30                 DeleteTeacher
31                 UpdateTeacher
32                 FindTeacher
33             cn.itcast.student
34                 AddStudent
35                 DeleteStudent
36                 UpdateStudent
37                 FindStudent
38                 
39     包的定义
40         package 包名;
41             多级包用.分开即可
42 
43     
44     注意事项:
45         A:package语句必须是程序的第一条可执行的代码
46         B:package语句在一个java文件中只能有一个
47         C:如果没有package,默认表示无包名
48         
49     带包的编译和运行:
50         A:手动式
51             a:编写一个带包的java文件。
52             b:通过javac命令编译该java文件。
53             c:手动创建包名。
54             d:把b步骤的class文件放到c步骤的最底层包
55             e:回到和包根目录在同一目录的地方,然后运行
56                 带包运行。
57                 
58         B:自动式
59             a:编写一个带包的java文件。
60             b:javac编译的时候带上-d即可
61                 javac -d . HelloWorld.java
62             c:回到和包根目录在同一目录的地方,然后运行
63                 带包运行。
64 */
65 package cn.itcast;
66 
67 class HelloWorld {
68     public static void main(String[] args) {
69         System.out.println("HelloWorld");
70     }
71 }

9、不同包间的访问

 1 /*
 2     Demo类,求和
 3 */
 4 package com.liuyi;
 5 
 6 public class Demo {
 7     public int sum(int a,int b) {
 8         return a + b;
 9     }
10 }
 1 /*
 2     Test类,测试
 3 
 4     导包:
 5         格式:import 包名;
 6             这种方式导入是到类的名称。
 7         注意:我们用谁就导谁。
 8         
 9     面试题:
10         package,import,class有没有顺序关系?
11         有。
12         package > import > class
13         
14         Package:只能有一个
15         import:可以有多个
16         class:可以有多个,以后建议是一个
17 */
18 package cn.itcast;
19 
20 import com.liuyi.Demo;
21 
22 class Test {
23     public static void main(String[] args) {
24         //Demo d = new Demo();
25         /*
26         com.liuyi.Demo d = new com.liuyi.Demo();
27         System.out.println(d.sum(10,20));
28         
29         com.liuyi.Demo d2 = new com.liuyi.Demo();
30         System.out.println(d2.sum(10,20));
31         
32         com.liuyi.Demo d3 = new com.liuyi.Demo();
33         System.out.println(d3.sum(10,20));
34         
35         com.liuyi.Demo d4 = new com.liuyi.Demo();
36         System.out.println(d4.sum(10,20));
37         */
38         
39         Demo d = new Demo();
40         System.out.println(d.sum(10,20));
41     }
42 }
43 
44 /*
45     第一个问题:找不到Demo
46     
47     第二个问题:程序包com.liuyi不存在
48     
49     第三个问题: Demo在com.liuyi中不是公共的; 无法从外部程序包中对其进行访问
50 */

10、修饰符的概述和总结

 1 /*
 2     权限修饰符:
 3                     本类    同一个包下(子类和无关类)    不同包下(子类)    不同包下(无关类)
 4         private     Y        
 5         默认        Y        Y
 6         protected    Y        Y                            Y
 7         public        Y        Y                            Y                Y
 8 */
 9 package com.liuyi;
10 
11 public class Father {
12     private void show() {
13         System.out.println("show");
14     }
15     
16     void show2() {
17         System.out.println("show2");
18     }
19     
20     protected void show3() {
21         System.out.println("show3");
22     }
23     
24     public void show4() {
25         System.out.println("show4");
26     }
27     
28     public static void main(String[] args) {
29         Father f = new Father();
30         f.show();
31         f.show2();
32         f.show3();
33         f.show4();
34     }
35 }

10、常见修饰符的使用

 1 /*
 2     修饰符:
 3         权限修饰符:private,默认的,protected,public
 4         状态修饰符:static,final
 5         抽象修饰符:abstract
 6         
 7     类:
 8         权限修饰符:默认修饰符,public
 9         状态修饰符:final
10         抽象修饰符:abstract
11         
12         用的最多的就是:public
13         
14     成员变量:
15         权限修饰符:private,默认的,protected,public
16         状态修饰符:static,final
17         
18         用的最多的就是:private
19         
20     构造方法:
21         权限修饰符:private,默认的,protected,public
22         
23         用的最多的就是:public
24         
25     成员方法:
26         权限修饰符:private,默认的,protected,public
27         状态修饰符:static,final
28         抽象修饰符:abstract
29         
30         用的最多的就是:public
31         
32     除此以外的组合规则:
33         成员变量:public static final
34         成员方法:public static 
35                   public abstract
36                   public final
37         
38 */
39 //此处不允许使用修饰符private
40 //此处不允许使用修饰符protected
41 //此处不允许使用修饰符static
42 public class Demo {
43     //成员变量
44     private int x = 10;
45     int y = 20;
46     protected int z = 30;
47     public int a = 40;
48     public final int b = 50;
49     public static int c = 60;
50     public static final int d = 70;
51     //此处不允许使用修饰符abstract
52     //abstract int e = 80;
53     
54     //构造方法
55     private Demo(){}
56     
57     Demo(String name){}
58     
59     protected Demo(String name,int age) {}
60     
61     public Demo(String name,int age,String address) {}
62     
63     //此处不允许使用修饰符static
64     //public static Demo(){}
65     //此处不允许使用修饰符final
66     //public final Demo() {}
67     //此处不允许使用修饰符abstract
68     //public abstract Demo(){}
69     
70     //成员方法
71     //static void show() {}
72     //abstract void show();
73     //final void show(){}
74 }

11、内部类概述

 1 /*
 2     内部类概述:
 3         把类定义在其他类的内部,这个类就被称为内部类。
 4         举例:在类A中定义了一个类B,类B就是内部类。
 5     
 6     内部的访问特点:
 7         A:内部类可以直接访问外部类的成员,包括私有。
 8         B:外部类要访问内部类的成员,必须创建对象。
 9     
10 */
11 class Outer {
12     private int num = 10;
13     
14     class Inner {
15         public void show() {
16             System.out.println(num);
17         }
18     }
19     
20     public void method() {
21         //找不到符号
22         //show();
23     
24         Inner i = new Inner();
25         i.show();
26     }
27     
28 }
29 
30 class InnerClassDemo {
31     public static void main(String[] args) {
32     
33     }
34 }

12、内部类分类及成员内部类的直接使用

 1 /*
 2     内部类位置
 3         成员位置:在成员位置定义的类,被称为成员内部类。    
 4         局部位置:在局部位置定义的类,被称为局部内部类。
 5         
 6         
 7     成员位置:在成员位置定义的类,被称为成员内部类。    
 8         
 9 */
10 class Outer {
11     private int num = 10;
12 
13     //成员位置
14     /*
15     class Inner {
16         
17     }
18     */
19     
20     
21 
22     public void method() {
23         //局部位置
24         class Inner {
25         
26         }
27     }
28 }
29 
30 class InnerClassDemo2 {
31     public static void main(String[] args) {
32         
33     }
34 }
 1 /*
 2     成员内部类:
 3         如何直接访问内部类的成员。
 4         外部类名.内部类名 对象名 = 外部类对象.内部类对象;
 5 */
 6 class Outer {
 7     private int num = 10;
 8     
 9     class Inner {
10         public void show() {
11             System.out.println(num);
12         }
13     }
14 }
15 
16 class InnerClassDemo3 {
17     public static void main(String[] args) {
18         //需求:我要访问Inner类的show()方法
19         //Inner i = new Inner();
20         //i.show();
21         
22         //格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
23         Outer.Inner oi = new Outer().new Inner();
24         oi.show();
25     }
26 }

13、成员内部类的常见修饰符

 1 /*
 2     成员内部类的修饰符:
 3         private 为了保证数据的安全性
 4         static 为了方便访问数据
 5             注意:静态内部类访问的外部类数据必须用静态修饰。
 6     
 7     案例:我有一个人(人有身体,身体内有心脏。)
 8         
 9         class Body {
10             private class Heart {
11                 public void operator() {
12                     System.out.println("心脏搭桥");
13                 }
14             }
15             
16             public void method() {
17                 if(如果你是外科医生) {
18                     Heart h = new Heart();
19                     h.operator();
20                 }
21             }
22         }
23         
24         按照我们刚才的讲解,来使用一下
25         Body.Heart bh = new Body().new Heart();
26         bh.operator();
27         //加了private后,就不能被访问了,那么,怎么玩呢?
28         Body b =  new Body();
29         b.method();
30 */
31 class Outer {
32     private int num = 10;
33     private static int num2 = 100;
34     
35     //内部类用静态修饰是因为内部类可以看出是外部类的成员
36     public static class Inner {
37         public void show() {
38             //System.out.println(num);
39             System.out.println(num2);
40         }
41 
42         public static void show2() {
43             //System.out.println(num);
44             System.out.println(num2);
45         }        
46     }
47 }
48 
49 class InnerClassDemo4 {
50     public static void main(String[] args) {
51         //使用内部类
52         // 限定的新静态类
53         //Outer.Inner oi = new Outer().new Inner();
54         //oi.show();
55         //oi.show2();
56         
57         //成员内部类被静态修饰后的访问方式是:
58         //格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
59         Outer.Inner oi = new Outer.Inner();
60         oi.show();
61         oi.show2();
62         
63         //show2()的另一种调用方式
64         Outer.Inner.show2();
65     }
66 }

练习:

 1 /*
 2     面试题:
 3         要求请填空分别输出30,20,10。
 4         
 5     注意:
 6         1:内部类和外部类没有继承关系。
 7         2:通过外部类名限定this对象
 8             Outer.this
 9 */
10 class Outer {
11     public int num = 10;
12     class Inner {
13         public int num = 20;
14         public void show() {
15             int num = 30;
16             System.out.println(num);
17             System.out.println(this.num);
18             //System.out.println(new Outer().num);
19             System.out.println(Outer.this.num);
20         }
21     }
22 }
23 class InnerClassTest {
24     public static void main(String[] args) {
25         Outer.Inner oi = new Outer().new Inner();
26         oi.show();
27     }    
28 }

14、局部内部类访问局部变量

 1 /*
 2     局部内部类
 3         A:可以直接访问外部类的成员
 4         B:在局部位置,可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
 5     
 6     面试题:
 7         局部内部类访问局部变量的注意事项?
 8         A:局部内部类访问局部变量必须用final修饰
 9         B:为什么呢?
10             局部变量是随着方法的调用而调用,随着调用完毕而消失。
11             而堆内存的内容并不会立即消失。所以,我们加final修饰。
12             加入final修饰后,这个变量就成了常量。既然是常量。你消失了。
13             我在内存中存储的是数据20,所以,我还是有数据在使用。
14 */
15 class Outer {
16     private int num  = 10;
17     
18     public void method() {
19         //int num2 = 20;
20         //final int num2 = 20;
21         class Inner {
22             public void show() {
23                 System.out.println(num);
24                 //从内部类中访问本地变量num2; 需要被声明为最终类型
25                 System.out.println(num2);//20
26             }
27         }
28         
29         //System.out.println(num2);
30         
31         Inner i = new Inner();
32         i.show();
33     }
34 }
35 
36 class InnerClassDemo5 {
37     public static void main(String[] args) {
38         Outer o = new Outer();
39         o.method();
40     }
41 }

使用反编译查看效果

15、匿名内部类的方法调用

 1 /*
 2     匿名内部类
 3         就是内部类的简化写法。
 4 
 5     前提:存在一个类或者接口
 6         这里的类可以是具体类也可以是抽象类。
 7     
 8     格式:
 9         new 类名或者接口名(){
10             重写方法;
11         }
12         
13     本质是什么呢?
14         是一个继承了该类或者实现了该接口的子类匿名对象。
15 */
16 interface Inter {
17     public abstract void show();
18     public abstract void show2();
19 }
20 
21 class Outer {
22     public void method() {
23         //一个方法的时候
24         /*
25         new Inter() {
26             public void show() {
27                 System.out.println("show");
28             }
29         }.show();
30         */
31         
32         //二个方法的时候
33         /*
34         new Inter() {
35             public void show() {
36                 System.out.println("show");
37             }
38             
39             public void show2() {
40                 System.out.println("show2");
41             }
42         }.show();
43         
44         new Inter() {
45             public void show() {
46                 System.out.println("show");
47             }
48             
49             public void show2() {
50                 System.out.println("show2");
51             }
52         }.show2();
53         */
54         
55         //如果我是很多个方法,就很麻烦了
56         //那么,我们有没有改进的方案呢?
57         Inter i = new Inter() { //多态
58             public void show() {
59                 System.out.println("show");
60             }
61             
62             public void show2() {
63                 System.out.println("show2");
64             }
65         };
66         
67         i.show();
68         i.show2();
69     }
70 }
71 
72 class InnerClassDemo6 {
73     public static void main(String[] args) {
74         Outer o = new Outer();
75         o.method();
76     }
77 }

16、匿名内部类的应用

 1 /*
 2     匿名内部类在开发中的使用
 3 */
 4 interface Person {
 5     public abstract void study();
 6 }
 7 
 8 class PersonDemo {
 9     //接口名作为形式参数
10     //其实这里需要的不是接口,而是该接口的实现类的对象
11     public void method(Person p) {
12         p.study();
13     }
14 }
15 
16 //实现类
17 class Student implements Person {
18     public void study() {
19         System.out.println("好好学习,天天向上");
20     }
21 }
22 
23 class InnerClassTest2 {
24     public static void main(String[] args) {
25         //测试
26         PersonDemo pd = new PersonDemo();
27         Person p = new Student();
28         pd.method(p);
29         System.out.println("--------------------");
30         
31         //匿名内部类在开发中的使用
32         //匿名内部类的本质是继承类或者实现了接口的子类匿名对象
33         pd.method(new Person(){
34             public void study() {
35                 System.out.println("好好学习,天天向上");
36             }
37         });
38     }
39 }

练习:

 1 /*
 2     匿名内部类面试题:
 3         按照要求,补齐代码
 4             interface Inter { void show(); }
 5             class Outer { //补齐代码 }
 6             class OuterDemo {
 7                 public static void main(String[] args) {
 8                       Outer.method().show();
 9                   }
10             }
11             要求在控制台输出”HelloWorld”
12 */
13 interface Inter { 
14     void show(); 
15     //public abstract
16 }
17 
18 class Outer { 
19     //补齐代码
20     public static Inter method() {
21         //子类对象 -- 子类匿名对象
22         return new Inter() {
23             public void show() {
24                 System.out.println("HelloWorld");
25             }
26         };
27     }
28 }
29 
30 class OuterDemo {
31     public static void main(String[] args) {
32         Outer.method().show();
33         /*
34             1:Outer.method()可以看出method()应该是Outer中的一个静态方法。
35             2:Outer.method().show()可以看出method()方法的返回值是一个对象。
36                 又由于接口Inter中有一个show()方法,所以我认为method()方法的返回值类型是一个接口。
37         */
38     }
39 }

------------

以上是关于Java笔记(10):面向对象--内部类的主要内容,如果未能解决你的问题,请参考以下文章

Java基础——面向对象(内部类)

Java 学习 day09

Java面向对象--代码块(初始化块)和内部类

菜鸟笔记 -- Chapter 6.4 面向对象的三大特性

Java面向对象(staticfinal匿名对象内部类包修饰符代码块)

大数据必学Java基础(四十六):内部类和面向对象项目实战