1、成员内部类
成员内部类是最普通的内部类,它的定义为位于另一个类的内部。
1.1 ,创建成员内部类的方法
成员内部类创建格式:
外部类类名.内部类类名 xxx = new 外部类类名. new内部类类名();
虽然成员内部类可以无条件地访问外部类的成员,而外部类想访问成员内部类的成员却不是这么随心所欲了。在外部类中如果要访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
1.2,成员内部类的访问控制修饰符
内部类就如同外部类的成员变量一样。public,default,protected,private四种访问控制符都是可以的,内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。
比如上面的例子,
如果成员内部类Inner用private修饰,则只能在外部类的内部访问,
如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;
如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。
1.3,成员内部类调用外部类的成员变量或者方法
成员内部类既可以调用内部类的成员变量也可调用外部类的成员变量
当成员内部类拥有和外部类同名的成员变量或者方法时,
会发生隐藏现象,即默认情况下访问的是成员内部类的成员。
对成员内部类和外部类同名的成员变量或者方法进行调用的访问格式:
外部类.this.成员变量
外部类.this.成员方法
例子:
//成员内部类
public class ChengYuanNeiBuLei {
public static void main(String[] args) {
CYOuterClass outer = new CYOuterClass();
//CYOuterClass.CYInnerClass inner = new CYOuterClass().new CYInnerClass();转化分为以下两种创建内部类方法
//(1)在外部创建内部类
//CYOuterClass.CYInnerClass inner = outer.new CYInnerClass();
//(2)在内部类所依附的外部类中创建创建内部类
CYOuterClass.CYInnerClass inner = outer.getInnerClass();
outer.out();
inner.in();
inner.testInner();
}
}
class CYOuterClass{//外部类
public CYInnerClass getInnerClass(){return new CYInnerClass();}
String outName = "外部类";
String sameName = "同名外部";
public void out(){
System.out.println("外部方法");
}
class CYInnerClass{//内部类
String inName = "内部类";
String sameName = "同名内部";
String name = "内部类变量";
public void in(){System.out.println("内部方法");}
public void testInner(){
String name = "局部变量";
System.out.println(name);//#内部类变量
System.out.println(this.name);//#局部变量
System.out.println("outName:" + outName);//#outName:外部类
System.out.println("inName:" + inName);//#inName:内部类
System.out.println("sameName:" + sameName);//#sameName:同名内部
System.out.println("sameName:" + this.sameName);//#sameName:同名内部,this指向CYInnerClass
System.out.println("sameName:" + CYOuterClass.this.sameName);//#sameName:同名外部
}
}
}
执行结果:
2、局部内部类
局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。
例子:
//局部内部类
public class JuBuNeiBuLei {
public static void main(String[] args) {
People people = new People();
people.getWoman("形参变量");
}
}
class People {
String peopleName = "people";
String sameName = "外部同名变量";
public People getWoman(final String methodName){
final String localName = "局部变量";
class Woman extends People{
String womanName = "woman";
String sameName = "局部内部类同名变量";
public Woman(){
System.out.println(methodName);//#形参变量
System.out.println(localName);//#局部变量
System.out.println(peopleName);//#people
System.out.println(womanName);//#woman
System.out.println(sameName);//#局部内部类同名变量
System.out.println(this.sameName);//#局部内部类同名变量
System.out.println(People.this.sameName);//#外部同名变量
}
}
return new Woman();
}
}
执行结果:
注:在局部内部类中调用外部类的变量或者方法的方式和规则是一样的。但局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
3、匿名内部类
匿名内部类由于没有名字,所以它的创建方式有些独特。匿名内部类也是定义在一个方法或者一个作用域里面的类,它和匿名内部类的区别在于匿名内部类的访问仅限于方法内或者该作用域内。
匿名内部类创建格式:
new 父类构造器(参数列表)/ 实现接口()
{
//匿名内部类的类体部分
}
匿名内部类的缺陷:
创建匿名内部类时它会立即创建一个该类的实例,该类的定义会立即消失,它仅能被使用一次,
若想重复使用一个类!建议重新定义类,而不是使用匿名内部类。
定义匿名内部类规则:
1、使用匿名内部类时,我们必须是继承一个类或者实现一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
2、匿名内部类中是不能定义构造函数的。(类都是匿名的,没法定义构造方法)
3、匿名内部类中不能存在任何的静态成员变量和静态方法。(类是匿名的,当然没有类方法或类变量)
4、匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
5、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
6、我们给匿名内部类传递参数的时候,若该形参需要被内部类里面使用时,那么该形参必须要为final。7、匿名内部类的初始化(使用构造代码块)
我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块能够达到为匿名内部类创建一个构造器的效果。
例子:
//利用构造代码块能够达到为匿名内部类创建一个构造器的效果
public class NiMingNeiBuLei {
public static void main(String[] args) {
NMOuterClass outer = new NMOuterClass();
//调用
NMInnerClass inner1 = outer.getInnerClass(59, "合格");
System.out.println(inner1.getStr());
NMInnerClass inner2 = outer.getInnerClass(60, "合格");
System.out.println(inner2.getStr());
}
}
class NMOuterClass {
public NMInnerClass getInnerClass(final int num, final String str){
return new NMInnerClass() {//new 抽象NMInnerClass父类构造器创建匿名类
int num;
String str_ ;
//使用构造代码块完成初始化
{
if(num >=60){
str_ = str;
}else {
str_ = "不合格";
}
}
public String getStr(){
return str_;
}
};
}
}
//NMInnerClass抽象类
abstract class NMInnerClass {
public abstract String getStr();
}
执行结果:
4、静态内部类
静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。
创建静态内部类对象格式:
外部类类名.内部类类名 xxx = new 外部类类名.内部类类名();
例子:
//静态内部类
public class JingTaiNeiBuLei {
public static void main(String[] args) {
//静态内部类与其它内部类的初始化方式不一样!
JTOuterClass.InnerClass inner = new JTOuterClass.InnerClass();
inner.test();
}
}
class JTOuterClass {
String outName = "我是外部类";
static String outType = "外部类";
//创建静态内部类
static class InnerClass {
String innerName = "我是内部类";
static String innerType = "静态内部类";
public InnerClass (){
System.out.println(outType);
}
public void test(){
System.out.println("调用内部类方法");
}
}
}
执行结果:
重点难点:
- 成员内部类可以无条件访问外部类的成员
- 局部内部类和匿名内部类只能访问局部final变量