java中的内部类
概述
将一个类定义在另一个类的里面,里面的那个类就称为内部类(内置类,嵌套类)
分析事物A时,发现该事物A描述中还有事物B,而且这个事物B还在访问被描述事物A的内容,将事物B定义成内部类来描述。
特点
- 内部类可以直接访问外部类中的成员;
- 外部类要访问内部类,必须建立内部类的对象;
举例:
package innerdemo;
public class InnerDemo1 {
public static void main(String[] args) {
Outer.Inner in = new Outer().new Inner(); // 直接访问内部类的方法
in.show();
Outer o = new Outer();//
o.method();
}
}
class Outer{
private int num = 3;
// 内部类
class Inner{
void show(){
num = 100;
System.out.println("内部类run..."+num);
}
}
public void method(){
Inner in = new Inner(); //外部类要访问内部类,必须建立内部类的对象;
in.show();
}
}
修饰符
-
直接访问外部类中的内部类中的成员:(不多见)
外部类名.内部类名 变量名 = new 外部类名(). new 内部类名();
Outer.Inner in = new Outer().new Inner();
in.show();
-
内部类是静态的类,相当于一个外部类。外部类只要一加载,内部类就存在了,所以直接new一个内部类对象出来;
Outer.Inner in1 = new Outer.Inner();
public class InnerClassDemo { public static void main(String[] args) { // 内部类是静态的。相当于一个外部类 Outer.Inner in1 = new Outer.Inner(); in1.show(); } } class Outer{ private static int num = 3; // 内部类 static class Inner{ void show(){ System.out.println("内部类run..."+num); } } }
-
如果内部类是静态的,成员是静态的,就不需要对象了。如果内部类中定义了静态成员,该内部类也必须是静态的。
package java_demo_2; public class InnerClassDemo { public static void main(String[] args) { Outer.Inner.function(); } } class Outer{ private static int num = 3; // 内部类 static class Inner{ void show(){ System.out.println("内部类run..."+num); } public static void function(){ System.out.println("内部类是静态的,成员也是静态的,不需要创建对象"+num); } } }
细节
package java_demo_2;
public class InnerClassDemo {
public static void main(String[] args) {
new Outer().method();
}
class Outer{
int num = 3;
// 内部类
class Inner{
int num = 4;
void show(){
int num = 5;
System.out.println(num); // num 5
System.out.println(this.num); // 4 局部和成员变量重名
System.out.println(Outer.this.num); // 3
}
}
void method(){
new Inner().show();
}
}
为什么内部类能直接访问外部类中成员呢?
那是因为内部类持有了外部类的引用。外部类名.this
局部内部类
内部类可以存放在局部位置上,可以放在方法中,放在代码块中。
class Outer1{
int num = 3;
void method(){
// 内部类在方法中
class Inner{
void show(){
System.out.println("方法中的内部类:"+num);
}
}
// 创建对象
Inner in = new Inner();
in.show();
}
{
// 内部类在代码块中
class Inner2{
void show(){
System.out.println("代码块中的内部类:" + num);
}
}
Inner2 in2 = new Inner2();
in2.show();
}
}
内部类在局部位置上只能访问局部中被final修饰的局部变量;
class Outer{
int num = 3;
void method(){
final int x = 9; // 这个好像都行 int x = 9 不报错;
class Inner{
void show(){
System.out.println("show..."+x); // 内部类在局部位置上只能访问局部中被final修饰的局部变量;
}
}
// 创建对象
Inner in = new Inner();
in.show();
}
}
匿名内部类
概述
内部类的简写格式。要简写,必须和外部类有关系。必须有前提:内部类必须继承或者实现一个外部类或者接口。
格式: new 父类or接口(){子类内容};
匿名内部类,其实就是一个匿名子类对象;这个对象比较胖。
按道理要先继承父类,重构方法,再创建对象调用方法如:
class Inner extends InnerDemo{ void show() { System.out.println("内部类run..." + num); } } public void method() { new Inner().show(); }
现在直接在方法里,进行new 父类(){重构方法;}
new InnerDemo(){ // 匿名内部类,new 他爹(){把方法重写;} void show(){ System.out.println("show..."+num); } }
具体代码如下:
public class InnerClassDemo {
public static void main(String[] args) {
new Outer().method();
}
}
// 抽象类
abstract class InnerDemo{
abstract void show();
}
class Outer {
private int num = 3;
// 内部类
// class Inner {
// void show() {
// System.out.println("内部类run..." + num);
// }
//
// }
public void method() {
// new Inner().show();
new InnerDemo(){ // 匿名内部类,new 他爹(){把方法重写;}
void show(){
System.out.println("show..."+num);
}
}.show();
}
}
应用
注释部分:普通内部类继承外部接口时代码:
interface Inter{
void show1();
void show2();
}
class Outer {
private int num = 3;
// 内部类
/*
class Inner implements Inter {
public void show1(){
}
public void show2(){
}
}
*/
public void method(){
// Inner in = new Inner();
// in.show1();
// in.show2();
Inter in = new Inter(){
public void show1(){
}
public void show2(){
}
};
in.show1();
in.show2();
}
}
通常的使用场景之一:当函数参数是接口类型时,而且接口中的方法不超过三个,可以用匿名内部类作为实际参数进行传递。
// 正常写
public class InnerClassDemo {
public static void main(String[] args) {
show(new InterImpl());
}
public static void show(Inter in){
in.show1();
in.show2();
}
}
interface Inter{
void show1();
void show2();
}
class InterImpl implements Inter{
public void show1(){}
public void show2(){}
}
// 简写,将匿名内作为实际参数传递
public class InnerClassDemo {
public static void main(String[] args) {
show(new Inter(){
public void show1(){}
public void show2(){}
});
}
public static void show(Inter in){
in.show1();
in.show2();
}
}
//接口
interface Inter{
void show1();
void show2();
}
分类
- 成员内部类(静态内部类和非静态内部类)
- 局部内部类
- 匿名内部类
成员内部类
- 静态内部类:直接通过外部类调用静态内部类的构造器
- 非静态内部类:先创建外部类的对象,再通过外部类的对象调用内部类的构造器或者
外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
package innerdemo;
/**
* @ClassName: InnerClassDemo
* @author: benjamin
* @version: 1.0
* @description: TODO
* @createTime: 2019/06/11/10:11
*/
public class InnerClassDemo {
public static void main(String[] args) {
// 创建静态内部类的对象
Person.Dog d = new Person.Dog();// 直接通过外部类调用静态内部类的构造器
//创建非静态内部类的对象
// Person.Bird b = new Person().new Bird();
Person p = new Person();
Person.Bird b = p.new Bird();// 通过外部类的对象调用内部类的构造器
b.info();
}
}
class Person{
String name;
int age;
// 非静态成员内部类
class Bird{
String name;
int id;
public Bird(){
}
public void setName(String name){
this.name = name;
}
public void info(){
show();
}
}
// 静态成员内部类
static class Dog{
String name;
int id;
public Dog(){
}
public void setName(String name){
this.name = name;
}
public void info(){
}
}
// 外部类的成员方法
public void show(){
System.out.println("我是外部类的show()方法");
}
}
局部内部类:常常使用一个方法,使其返回值为某个类或接口的对象,而这个类或接口在方法内部创建。举例:
匿名内部类:
举例:
class OuterJu{
// 局部内部类的使用
public Comparable getComparable(){
//1.创建一个实现Comparable接口的类:局部内部类
class MyComparable implements Comparable{
@Override
public int compareTo(Object o) {
return 0;
}
}
// 2. 返回一个实现类的对象
return new MyComparable();
}
// 匿名内部类的使用
public Comparable getComparable1(){
//返回一个实现Comparable接口的匿名内部类的对象
return new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
}
}
细节
细节1
主函数会报错,因为无法访问非静态类,而且由于是静态不能采用this.new Inner()
方法:需要将Inner定义成静态类;
package java_demo_2;
/**
* @ClassName: InnerClassDemo5
* @author: benjamin
* @version: 1.0
* @description: TODO
* @createTime: 2019/04/13/22:28
*/
public class InnerClassDemo5 {
class Inner{// 如果不定义成静态,主函数会报错;
}
public static void main(String[] args) {
new Inner(); //无法从静态上下文中引用非静态 变量 this
// 因为主函数是静态的;
}
public void method(){
new Inner(); // 正确
}
public static void show(Inter in){
in.show1();
in.show2();
}
}
interface Inter{
void show1();
void show2();
}
细节2:
// 正确的
package java_demo_2;
public class InnerClassDemo6 {
public static void main(String[] args) {
new Outer6().method();
}
}
class Outer6{
// 创建的匿名内部类相当于
// class Inner6 extends Object{
// public void show(){
// System.out.println("show run");
// }
// }
// new Inner6.show();
void method(){
new Object(){
public void show(){
System.out.println("show run");
}
}.show();
}
}
编译看左边
package java_demo_2;
public class InnerClassDemo6 {
public static void main(String[] args) {
new Outer6().method();
}
}
class Outer6{
void method(){
Object obj = new Object(){
public void show(){
System.out.println("show run");
}
};
obj.show();
// Error:(35, 13) java: 找不到符号
// 因为匿名内部类这个子类对象被向上转型为Object类型,
// 这样就不再使用子类特有的方法了;
}
}