注意:非内部类(外部类或接口)不能被声明为private(私有的)或protected(受保护的),也不能被static修饰可以被final修饰。这是为何???
对于外部类(顶级类)来说,只有两种修饰符:public和默认。因为外部类的上一单元就是包。所以外部内就只有这两种作用域同包(包控制权限)或其他任何地方(公开访问权限)。protected的不同包子类可以访问那是针对属性和方法的。类就两种访问修饰包内和包外。
一、成员内部类
1、成员内部类
内部类的实例一定要绑定在外部类的实例上,如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。
内部类方法中能任意访问外部类的成员属性和方法。外部类的成员方法中访问内部类的属性,需要创建内部类的对象才可以任意访问。
public class People {
private String pname="张三";
private int age=18;
public void sayHello(){
System.out.println("Hello!!!");
//1、外部类的方法中可以使用内部类的属性和方法
Address address=new Address();
address.addressName="湖北省武汉市洪山区";
address.contactName="张三";
address.showAddressInfo();
}
/**
* 定义普通内部类
*/
class Address{
private String addressName;//收货地址
private String contactName;//联系人
private int age=18;
public void showAddressInfo(){
System.out.println("联系人:"+contactName+"\t"+"收货地址:"+addressName);
//System.out.println("访问外部类:"+pname);
}
public void showAge(People people){
System.out.println(age);//就近原则,自己的age,内部类
System.out.println("访问内部类属性:"+this.age);//访问内部类自己的age
System.out.println("访问外部类属性:"+people.age);//访问外部类的age
System.out.println(People.this.age);//访问外部类属性
}
}
}
public class TestPeople {
public static void main(String[] args) {
//创建内部类的对象,必须依赖外部类对象
//People.Address address=new People.Address();报错
People people = new People();
People.Address address = people.new Address();
//address.showAddressInfo();
people.sayHello();
address.showAddressInfo();//外部类访问内部类的属性赋值,并没改变内部类真实属性。
//是因为我的People的sayHello里面new的address对象跟我现在外面TestPeople里面的new的
//对象不是一个对象。所有现在还是为空。除非sayHello方法中返回对象地址,才行。这样才是拿到了同一对象
address.showAge(people);
外部类类名 外部引用名 = new 外部类类名();
外部类类名.内部类类名 内部类引用名 = 外部引用名.new 内部类类名();
2、内部类向上转型为接口
将接口实现类作为内部类,将其是私有化,定义一个外部类的成员方法获取接口实现对象。
public interface OutInterface {
void f();
}
public class OuterClass {
private class InnerClass implements OutInterface {
public InnerClass(String s) {
System.out.println(s);
}
@Override
public void f() {
System.out.println("访问内部类中的方法f()方法");
}
}
public OutInterface doit() {
return new InnerClass("访问内部类构造方法");
}
public static void main(String[] args) {
OuterClass outerClass=new OuterClass();
OutInterface outInterface=outerClass.doit();
outInterface.f();
}
}
3、使用this关键字获取内部类与外部类的引用
内部类获取外部类的引用:外部类.this
外部类类名.this.属性名(方法名)
public class TheSameName {
private String name="我是外部类的Name";
private class Inner{
private String name="我是内部类的Name";
public void showName(){
System.out.println(name);//就近原则
System.out.println("====================================");
System.out.println(this.name);//自己的属性
System.out.println("====================================");
System.out.println(TheSameName.this.name);//外部类属性
}
}
public static void main(String[] args) {
TheSameName out=new TheSameName();
TheSameName.Inner in=out.new Inner();
in.showName();
}
}
二、局部内部类(方法内部类)
内定义在方法中,所以内部类的调用只能在方法中实现,其生命周期与方法同步。
public class OuterClass {
private String name = "我是顶级类的属性";
public void method() {
String methodName = "我是方法的属性";
class MethodInnerClass {
String str = "我是方法内部类的属性";
public void Innermethod() {
System.out.println(name);
System.out.println(methodName);
System.out.println(str);
}
}
MethodInnerClass methodInnerClass = new MethodInnerClass();
methodInnerClass.Innermethod();
}
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
outerClass.method();
}
}
三、匿名内部类
匿名内部类就像实现类实现了接口,子类重写父类的方法。
new 接口(){重写接口的所有方法};
public interface IStudent {
public void study();
public void sleep();
}
public class Student {
IStudent iStudent=new IStudent() {
@Override
public void study() {
System.out.println("学习");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
};
public static void main(String[] args) {
Student student=new Student();
student.iStudent.sleep();
student.iStudent.study();
}
}
new 父类(){重写父类的方法};
public class Animal {
public void eat(){
System.out.println("eat");
}
}
public class Dog{
Animal animal=new Animal(){
@Override
public void eat() {
super.eat();
}
};
public static void main(String[] args) {
Dog dog=new Dog();
dog.animal.eat();
}
}
四、静态内部类
由于内部类是静态的无需外部类创建对象就存在静态内存中了,无需像成员内部类那样。
静态内部类是无法访问外部成员属性和方法的,因为外部类的成员属性和方法是需要创建对象才会在堆内存给它们开辟内存空间并赋初始值。
引用方式:外部类名.静态内部类名 静态内部类名=new 外部类名.静态内部类名();
public class OuterClass {
private String name="我是外部类的属性";
static class InnerClass{
private String nameInnerClass="我是静态内部类的属性";
public void method(){
System.out.println(nameInnerClass);
//System.out.println(OuterClass.this.name);不能访问外部类的属性,因为静态内中没有对象
//要想访问就得创建外部类的对象
}
}
public static void main(String[] args) {
//由于内部类是静态的无需外部类创建对象就存在静态内存中了
//外部类名.静态内部类名 静态内部类名=new 外部类名.静态内部类名();
OuterClass.InnerClass innerClass=new OuterClass.InnerClass();
innerClass.method();
}
}
五、内部类的继承
同样内部类也可以被继承,但是必须手动一个有参的构造方法,并且该方法的参数必须是内部类的外部类的引用,同时需要引用.super()的语句。因没有被static修饰的内部类是被捆绑在外部类的对象上面的,所以这里需要传入一个外部类的引用到内部类的子类的构造函数中。
public class ATest {
class BTest{
}
}
public class ATestTest extends ATest.BTest {
public ATestTest(ATest aTest){
aTest.super();
}
}
本文地址:https://blog.csdn.net/LUOHANG22/article/details/109156390
希望与广大网友互动??
点此进行留言吧!