java中的内部类
1.什么是内部类?
类中的类【将一个java类定义在另一个java类里面,那么定义里面的java类就是内部类】。
内部类定义在java类里面的类。
外部类包含内部类的类就是外部类。
在以前我们认为一个java类中有两个基本元素【变量和方法】,当我们认识类内部类以后,现在我们认为一个java类中可以有三个元素【变量和方法,类[内部类]】。
2.内部类的分类
1.成员内部类
2.方法内部类
3.匿名内部类
4.静态嵌套类
3.成员内部类
3.1 成员内部类---内部类---作为外部类的成员-----类中的成员变量
成员内部类基本结构
package com.click369.test;
public class MyClass {
public class InnerClass{
}
}
上面代码中MyClass 是外部类,InnerClass就是一个成员内部类
3.2成员内部类里面自己元素的访问
1.在成员内部类中不能出现使用static修饰的任何元素【类变量/类方法】
2.成员内部类的构造方法中可以访问成员内部类的实例变量和实例方法,默认使用this访问。此处的this指的是这个成员内部类的对象,this是可以省略的。
成员内部类的构造方法中可以访问成员内部类的其他的构造方法,new + 构造方法();
3.成员内部类的实例造方法中可以访问成员内部类的实例变量和实例方法,默认使用this访问。此处的this指的是这个成员内部类的对象,this是可以省略的。
成员内部类的实例方法中可以访问成员内部类的构造方法,new + 构造方法();
3.3成员内部类里面访问外部类的元素
1.成员内部类中的构造方法中可以访问其外部类的实例变量和实例方法,默认是外部类的类名.this访问
此处的外部类的类名.this代表外部类的对象
我们在成员内部类中要使用外部类的对象默认外部类的类名.this。
外部类的类名.this是可以省略
2.成员内部类中的构造方法中可以访问其外部类的类变量和类方法,默认是外部类的类名访问,也以外 部类的类名.this访问
类名/外部类的类名.this是可以省略
3.成员内部类中的实例方法中可以访问其外部类的实例变量和实例方法,默认是外部类的类名.this访问
此处的外部类的类名.this代表外部类的对象
我们在成员内部类中要使用外部类的对象默认外部类的类名.this。
外部类的类名.this是可以省略
4.成员内部类中的实例方法中可以访问其外部类的类变量和类方法,默认是外部类的类名访问,也以外 部类的类名.this访问
类名/外部类的类名.this是可以省略
3.4在外部类中访问成员内部类的元素
外部类的构造方法可以访问内部类的变量/方法,通过内部类的对象访问。
外部类的实例方法可以访问内部类的变量/方法,通过内部类的对象访问
外部类的类方法中无法创建出内部类的对象,因此是无法访问内部类的变量和方法
3.5在其他类中访问成员内部类的元素
在其他类中访问内部类中的元素时需要先创建外部类的对象,然后在创建内部对象
package com.click369.test;
import com.click369.test.TestClass;
public class TestMain {
public TestMain(){
//先创建外部类对象,然后在创建内部类对象
TestClass.InnerClass inner=new TestClass().new InnerClass();
//InnerClass inner=new TestClass().new InnerClass();
//System.out.println("inner_private_string=="+inner.inner_private_string);
System.out.println("inner_string=="+inner.inner_string);
System.out.println("inner_protected_string=="+inner.inner_protected_string);
System.out.println("inner_public_string=="+inner.inner_public_string);
inner.innert_Method1();
inner.innert_Method2();
inner.innert_Method3();
//inner.innert_Method4();
}
public void method(){
//先创建外部类对象,然后在创建内部类对象
TestClass.InnerClass inner=new TestClass().new InnerClass();
//InnerClass inner=new TestClass().new InnerClass();
//System.out.println("inner_private_string=="+inner.inner_private_string);
System.out.println("inner_string=="+inner.inner_string);
System.out.println("inner_protected_string=="+inner.inner_protected_string);
System.out.println("inner_public_string=="+inner.inner_public_string);
inner.innert_Method1();
inner.innert_Method2();
inner.innert_Method3();
//inner.innert_Method4();
}
public static void main(String[] args) {
//先创建外部类对象,然后在创建内部类对象
TestClass.InnerClass inner=new TestClass().new InnerClass();
//InnerClass inner=new TestClass().new InnerClass();
//System.out.println("inner_private_string=="+inner.inner_private_string);
System.out.println("inner_string=="+inner.inner_string);
System.out.println("inner_protected_string=="+inner.inner_protected_string);
System.out.println("inner_public_string=="+inner.inner_public_string);
inner.innert_Method1();
inner.innert_Method2();
inner.innert_Method3();
//inner.innert_Method4();
}
}
4.方法内部类
方法内部类就是定义在一个方法中的java类,类似于一个方法的局部变量。
4.1.一个方法的局部变量是不能有任何修饰符,因此上方法内部类在定义的时候是没有访问修饰符存在的。
package com.click369.test1;
public class MyClass {
public MyClass(){
class InnerClass1{
}
}
public void method(){
class InnerClass2{
}
}
public static void staticMethod(){
class InnerClass3{
}
}
}
4.2.方法内部类中不能有static修饰的类变量和类方法
4.3.在方法内部类中访问方法内部类中定义的变量和方法
1.方法内部类中的构造可以访问本方法内部类中的变量、方法,默认this访问,this可以省略
2.方法内部类中实例方法可以访问本方法内部类中的变量、方法,默认this访问,this可以省略
4.4.在方法内部类中访问可以方法中定义的局部变量,默认变量名称访问。
4.5.方法内部类的方法中可以访问外部类的实例变量/实例方法,默认外部类的类名.this,外部类的类名.this可以省略
4.6.方法内部类的方法中可以访问外部类的类变量/类方法,默认外部类的类名访问,也可以外部类的类名.this访问,可以省略外部类的类名/外部类的类名.this
4.7.外部类中是不能访问方法内部类中的元素,方法内部类就类似于局部变量,跨出本方法就失效。
4.8.在定义这个方法内部类的方法中可以访问方法内部类中的变量和方法,对象访问
5.匿名内部类
匿名内部类---没有名字的内部类。【充当某一个类/接口的子类】
例如:某一个类的方法的参数是一个抽象类/接口,当我们调用这个方法的时候需要给这个方法传递参数,那么这个参数可以是抽象类的子类对象/上转型对象,实现该接口的子类对象/接口回调对象。
不管抽象类的子类对象/上转型对象,在传递参数之前我们都得额外的创建一个抽象类的子类。
不管实现该接口的子类对象/接口回调对象,在传递参数之前我们都得额外的创建一个接口的子类。
想一想:我们在传递参数的时候能不能不去额外的常见这个抽象类的子类/接口的子类?
可以,使用匿名内部类就可以,因为匿名内部类可以用来充当当某一个类/接口的子类。
5.1继承式的匿名内部类
public abstract class MyClass {
public abstract void myclassMethod();
}
public class TestClass {
/**
* 这个实例方法的参数是抽象类类型
* @param mc
*/
public void methodClass(MyClass mc){
System.out.println("这个实例方法的参数是抽象类类型");
}
}
public class TestMain {
public static void main(String[] args) {
TestClass tc=new TestClass();
/**
* 参数可以是匿名内部类【可以充当子类】
*/
tc.methodClass(new MyClass(){
@Override
public void myclassMethod() {
System.out.println("重写父类MyClass抽象类的抽象方法");
}});
/*
* new MyClass(){
@Override
public void myclassMethod() {
System.out.println("重写父类MyClass抽象类的抽象方法");
}
}
这种结构就是一个匿名内部类了,这个类是没有名字的,
“MyClass”并不是这个类的名称,他是父类的名称。
而这一段代码是MyClass类的子类。
*/
}
}
5.2接口式的匿名内部类
public interface MyInterface {
void myinterfaceMethod();
}
public class TestClass {
/**
* 这个实例方法的参数是接口类型
* @param mi
*/
public void methodInterface(MyInterface mi){
System.out.println("这个实例方法的参数是接口类型");
}
}
public class TestMain {
public static void main(String[] args) {
TestClass tc=new TestClass();
/**
* 参数可以是匿名内部类【可以充当子类】
*/
tc.methodInterface(new MyInterface(){
@Override
public void myinterfaceMethod() {
System.out.println("重写父接口中的抽象方法");
}});
/*
* new MyInterface(){
@Override
public void myinterfaceMethod() {
System.out.println("重写父接口中的抽象方法");
}}
这种结构就是一个匿名内部类了,这个类是没有名字的,
"MyInterface"并不是这个类的名称,他是父接口的名称。
而这一段代码是MyInterface接口的子类。
*/
}
}
优点:减少了子类的创建 , 缺点:不容易阅读/理解
6.静态嵌套类
静态嵌套类实际上是添加了static修饰符的成员内部类。
public class MyClass {
public static class InnerClass{
}
}
6.1静态嵌套类中可以有实例变量,类变量,构造方法,实例方法,类方法
6.2静态嵌套类中的构造方法和实例方法中可以调用这个静态嵌套类中的实例变量和实例方法,默认this调用,可以省略this。
6.3静态嵌套类中的构造方法和实例方法中可以调用这个静态嵌套类中的类变量和类方法,默认类名调用,也可以this调用,可以省略类名/this
6.4静态嵌套类中的类方法中不能有this
6.5静态嵌套类中的类方法里面不能调用实例变量和实例方法 ,可以调用这个静态嵌套类中的类变量和类方法,默认类名调用,可以省略类名。
6.6静态嵌套类中的构造方法,实例方法,类方法中可以访问外部类的实例变量/实例方法,对象访问
6.7静态嵌套类中的构造方法,实例方法,类方法中可以访问外部类的类变量/类方法,默认类名访问,也可以对象访问,可以省略类名/对象。
6.8外部类的构造方法,实例方法,类方法中可以访问静态嵌套类的实例变量/实例方法,对象访问,不能省略
6.9外部类的构造方法,实例方法,类方法中可以访问静态嵌套类的类变量/类方法,默认类名访问,可以对象访问,不能省略类名/对象.
6.10在其他类的构造方法,实例方法,类方法中可以访问静态嵌套类的实例变量和实例方法,对象访问,看导包的结果来创建对象。
import com.click369.test2.MyClass;
MyClass.InnerClass inner= new MyClass.InnerClass();
import com.click369.test2.MyClass.InnerClass;
InnerClass inner= new InnerClass();
6.11在其他类的构造方法,实例方法,类方法中可以访问静态嵌套类的类变量和类方法,默认类名访问 ,看导包的结果
import com.click369.test2.MyClass.InnerClass;
InnerClass.static_method();
import com.click369.test2.MyClass;
MyClass.InnerClass.static_method();
也可以对象访问,看导包的结果来创建对象。
import com.click369.test2.MyClass;
MyClass.InnerClass inner= new MyClass.InnerClass();
import com.click369.test2.MyClass.InnerClass;
InnerClass inner= new InnerClass();
通常情况下使用静态嵌套类的时候,往往给静态嵌套类中定义静态元素【static】,在访问的时候,可以用类名一路点调用。
例如:Android程序开发的时候有一个R.java文件,典型的静态嵌套类结构。
延伸思考:能不能有内部接口【接口中包含接口】????