Java学习之内部类
Java之内部类
这是我在看刘意老师的Java视频的笔记。仅供学习,转载请注明来源。
什么是内部类?
把类定义在其他类的内部,这个类就被成为内部类
举例:在类A中定义一个类B,类B就是内部类
内部类的特点
A:内部类可以直接访问外部类的成员,包括私有
B:外部类要访问内部类的成员,必须创建对象
内部类的位置
成员位置:在成员位置定义的类,被成为成员内部类
如何访问内部类的成员:
//格式:外部类名.内部类名.对象名 = 外部类对象.内部类对象
//代码:Outer.Inner oi = new Outer().new Inner();
成员内部类的修饰符:
-
Private 为了保证数据的安全性
-
Static 为了数据访问更方便
//用静态修饰后内部类访问方式:
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名()
//代码:Outer2.Inner2 oi = new Outer2.Inner2();
局部位置:在局部位置定义的类,被成为局部内部类
A:可以直接访问外部类的成员
B:可以创建内部类对象,通过对象调用内部类方法,来使用局部内部类功能
匿名内部类:就是内部类的简化写法
前提:存在一个类或者接口
这里的类可以是具体类也可以是抽象类
本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名匿名对象
/*
* 格式:
* new 类名或者接口名() {
* 重写方法;
* }
*/
new Inner2() {
public void show() {
System.out.println("show");
}
} ;
//值得关注的是:上面的代码等价于一个对象(这个理解很重要,在下面的代码会体现)
//匿名内部类在开发中的使用:
package 内部类;
public interface Person {
public abstract void study();
}
package 内部类;
//实现类
public class Student implements Person {
@Override
public void study() {
System.out.println("好好学习,天天向上");
}
}
package 内部类;
public class PersonDome {
public void method(Person p) {
//接口名作为形式参数
//其实这里需要的不是接口,而是该接口的实现类的对象
p.study();
}
}
package 内部类;
//测试类
public class Dome1 {
public static void main(String[] args) {
Person p = new Student();
PersonDome pd = new PersonDome();
pd.method(p);//好好学习,天天向上
//匿名内部类在开发中的应用
//本质
//安卓用的多,因为用完就是垃圾,只能用一次
pd.method(new Person() {
@Override
public void study() {
System.out.println("学习好啊好");//学习好啊好
}
});
}
}
注意
- 注意:static不能修饰类,这个类指外部类,不包括内部类;内部类用静态修饰是因为内部类可以看成是外部类的成员,最好搭配public修饰
- 注意:静态内部类访问的外部类数据必须用静态修饰
- 注意:静态方法可以通过类名调用,因此静态内部类可以通过类名调用
- 注意:匿名内部类在开发中的应用可以用defalut修改,但是管理员还没想出来
实例
基本格式:
```java
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 Outer{
//成员位置
class Inner{}
//局部内部类
public void method(){ class Inner{} }
}
成员内部类+private
*这里是对内部类对关键字private的解释
* 案例:我有一个人(人有身体,身体有心脏(心脏是私有的,不能随便给人看的))
* 类(心脏没加private):
* class Body{
* class Heart{
* public void operator(){
* System.out.println("心脏搭桥");
* }
* }
* }
* //没加private,直接创建对象调用operator()//
* Body.Heart bh = new Body().new Heart();
* bh.operator();
* 输出:心脏搭桥
*
* //心脏加了private,调用operator()
* //加入构造方法调用
* //加入private,可以更好地保护数据
* public void method(){
* Heart h = new Heart();
* if(你是外科医生){//你还得是医生,也就是有权限看的用户,才能调用内部类的方法
* h.operator();
* }
* }
*
* main方法:
* Body b = new Body();
* b.method();
* 输出:心脏搭桥
*
心脏架桥源码:
package语句来当不同文件代码的分隔符。即包语句上面是一个文件的代码,包语句下面是另一个文件的代码
私有:
package 内部类;
public class Body {
private class Heart {
public void operator() {
System.out.println("心脏搭桥");
}
}
public void method() {
Heart h = new Heart();
h.operator();
}
}
package 内部类;
public class Dome1 {
public static void main(String[] args) {
Body b = new Body();
b.method();
}
}
未私有:
package 内部类;
public class Body {
class Heart {
public void operator() {
System.out.println("心脏搭桥");
}
}
}
package 内部类;
public class Dome1 {
public static void main(String[] args) {
Body.Heart bh = new Body().new Heart();
bh.operator();
}
}
两个结果都是:心脏架桥
例题代码:
package 内部类;
public class Outer {
private int num1 = 10;
private int num2 = 20;
class Inner {
public void show() {
System.out.println(num1);
}
}
public void show2() {
System.out.println(num2);
}
}
package 内部类;
public class Dome1 {
public static void main(String[] args) {
//需求:我要访问Inner类的show()方法
//直接访问
Outer.Inner oi = new Outer().new Inner();
oi.show();//10
//oi.show2();
//Error:(9, 11) java: 找不到符号
// 符号: 方法 show2()
// 位置: 类型为内部类.Outer.Inner的变量 oi
Outer o = new Outer();
//o.show();
//Error:(12, 10) java: 找不到符号
// 符号: 方法 show()
// 位置: 类型为内部类.Outer的变量 o
o.show2();//20
}
}
内部类+static:
package 内部类;
public class Outer {
private static int num2 = 20;
public static class Inner {
//静态内部类的非静态方法
public void show() {
System.out.println(num2);
}
//静态内部类的静态方法
public static void show2() {
System.out.println(num2);
}
}
}
ppackage 内部类;
public class Dome1 {
public static void main(String[] args) {
//成员内部类被静态修饰后的访问方式
//格式:外部类名.内部类名 对象名 = new 外部类名.内部类名()
Outer.Inner oi = new Outer.Inner();
oi.show();//20
oi.show2();//20
//show2的另一种调用方式(匿名调用)
Outer.Inner.show2();//20
}
}
局部内部类:
package 内部类;
public class Outer {
private int num = 10;
public void method() {
class Inner {
public void show() {
System.out.println(num);
}
}
//在调用这个方法的时候,就一定会调用成功内部类
//因为创建内部类,调用内部类方法的语句都会执行
Inner i = new Inner();
i.show();
}
}
package 内部类;
public class Dome1 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();//10
}
}
匿名内部类:
*/格式
package 内部类;
interface Inner {
public abstract void show();
}
package 内部类;
class Outer {
public void method() {
new Inner() {
@Override
public void show() {
System.out.println("show");
}
}.show();
}
}
package 内部类;
public class Dome2 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();//show
}
}
匿名内部类+多接口
package 内部类;
interface Inner {
public abstract void show();
public abstract void show2();
}
package 内部类;
public class Outer {
//当接口只有一个方法的时候
/*
public void method() {
//子类匿名对象
//接口子类的实现类对象
new Inner() {
public void show() {
System.out.println("show");
}
}.show();
*/
/*
//当接口只有两个方法的时候
public void method() {
new Inner() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show();//重写接口的两个方法并且调用第一个方法
new Inner() {
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
}.show2();//重写接口的两个方法并且调用第二个方法
*/
//由第二段代码得出由很多段代码是重复的
//如果我是很多个方法,就很麻烦了
// 那么,我们有改进的方案
public void method() {
Inner i = new Inner() {//多态
//由第一段代码知道new开始的代码是子类匿名对象
//那么可以利用多态将子类对象赋给父接口
//编译看左边,Inner由show()和show2()方法
//运行看右边,所以调用子类匿名对象new Inner的方法
public void show() {
System.out.println("show");
}
public void show2() {
System.out.println("show2");
}
};
i.show();
i.show2();
}
//三段代码一定要两个在注释状态
//否则会报错,因为作用都是相同的
}
public class Dome2 {
public static void main(String[] args) {
Outer o = new Outer();
o.method();//show show2
}
}
写在最后
这篇文章是视频笔记,既然是笔记,就肯定会有的地方是跟不上变化的。但是耐心看完并且敲代码之后,内部类的基础也学得差不多了。
有答案的我都写在注释里。
如果有错误,欢迎批评和讨论。