目录
一、内部类的概念
在 Java 中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现。
public class OutClass {//外部类
class InnerClass{//内部类
}
}
注意事项:
1、内部类一定是定义在class 类名{}之中的类,定义在class 类名{}之外的,哪怕是在一份文件中,也并不能称为内部类。例如:
public class A{
}
class B{
}
//A和B两个类是独立的,无内外部类一说
2、内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件。
二、内部类的分类
public class OutClass {
//普通内部类
class InnerClass1{
}
//静态内部类
static class InnerClass2{
}
{
//定义在实例代码块中的 局部内部类
class InnerClass3{
}
}
static{
//定义在静态代码块中的 局部内部类
class InnerClass4{
}
}
public void method(){
//定义在方法中的 局部内部类
class InnerClass5{
}
{
//方法中的普通代码块中也可以定义局部内部类
class InnerClass6{
}
}
}
}
根据内部类定义的位置不同,可以分为:
成员内部类:普通内部类和静态内部类。
局部内部类和匿名内部类。
三、成员内部类
1、普通内部类
未被static修饰的成员内部类。
public class OutClass {//外部类
private int a;
private int b;
private int c;
public void method1(){
a=100;
System.out.println(a);
}
public void method2(){
System.out.println(b);
}
class InnerClass{ //普通内部类
private int c; //与外部类成员变量名称相同的内部成员变量
public void methodInner() {
//在内部类中可以直接访问外部类任意限定符的成员变量和方法
b = 150;
method1();
method2();
//在访问与外部类成员名称相同的成员时,优先访问内部类自己的成员
c = 300;
System.out.println(c);
//要访问外部类中的同名成员必须使用——— 外部类名.this.成员名 来访问
OutClass.this.c = 400;
System.out.println(OutClass.this.c);
}
}
public static void main(String[] args) {
//创建内部类对象
OutClass.InnerClass innerclass1=new OutClass().new InnerClass();
//也可以先创建外部类对象,再创建内部类对象
OutClass outclass=new OutClass();
//注意当在不同文件中创建其内部类对象一定需要加上该内部类的外部类名,同一文件下可加可不加
OutClass.InnerClass innerclass2=outclass.new InnerClass();
innerclass2.methodInner();
}
}
/*
100
150
300
400
*/
注意事项:
1、普通内部类中可以直接访问外部类中的所有方法。
2、普通内部类成员的位置与外部类成员位置相同,都受public,private等限定符的限制。
3、在普通内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员 来访问。
4、要创建普通内部类对象,要先创建外部类的对象。在创建内部类对象时,如果该内部类在当前文件,则在创建对象语句最前面不需要外部类名,如果在不同文件,那么一定要指明该内部类的外部类名。
5、 普通内部类中包含了一个指向外部类对象的引用。
6、外部类中,不能直接访问内部类中的成员,如果要访问必须先要创建内部类的对象。
public class OutClass1 {
private int a;
public void method(){
System.out.println(c); //在外部类中直接访问内部类成员,编译报错
}
class InnerClass{
private int c;
}
}
public class OutClass1 {
private int a;
public void methodOut(){
InnerClass I2=new InnerClass();//在外部类方法中创建内部类对象可以直接创建
System.out.println(I2.c);
}
class InnerClass{
private int c;
}
}
从堆和栈的角度来看内部类和外部类:
2、静态内部类
被static修饰的成员内部类称为静态内部类。
public class OutClass {//外部类
private int a;
static int b; //静态变量
public void method1(){
}
public static void method2(){ //静态方法
}
static class InnerClass{ //静态内部类
public void methodInner() {
//在静态内部类中只能访问外部类的静态成员和方法
// a=100;编译失败,a不是外部类的成员变量
b = 150;
// method1();编译失败,method1不是外部类的成员方法
method2();
}
}
public static void main(String[] args) {
//静态内部类的创建
InnerClass innerclass=new InnerClass();
//成员访问
innerclass.methodInner();
}
}
注意事项:
1、在内部类中只能访问外部类中的静态成员。
2、创建静态内部类对象时,不需要先创建外部类对象。
3、成员内部类,经过编译之后会生成自己独立的字节码文件,例如下:
四、局部内部类
定义在外部类的方法体或者{}中,该种内部类只能在其定义的位置使用。
public class OutClass {//外部类
int a=10;
public void method(){ //外部类方法
int b=10;
class InnerClass{ //局部内部类,只能在该方法体内部使用
public void methodInnerClass(){
System.out.println(a);
System.out.println(b);
}
}
InnerClass innerclass=new InnerClass();
innerclass.methodInnerClass();
}
public static void main(String[] args) {
//InnerClass innerclass=null; 编译失败
}
}
注意事项:
1、局部内部类只能在所定义的方法体内部使用。
2、局部内部类不能被public、static等限定符修饰。
3、同样编译之后局部内部类会生成自己的字节码文件。
命名格式:外部类名$x内部类名.class, 其中x是一个整数。
五、对象的打印
public class Person {
String name;
String gender;
int age;
public Person(String name,String gender,int age){
this.name=name;
this.gender=gender;
this.age=age;
}
public static void main(String[] args) {
Person person=new Person("luka","man",21);
System.out.println(person);
}
}
打印结果: 并不是对象本身。
如果想要打印对象本身,那么需要重写toString方法。
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public String toString() { //重写了toString方法
return "[" + name + "," + gender + "," + age + "]";
}
public class Person {
String name;
String gender;
int age;
public Person(String name,String gender,int age){
this.name=name;
this.gender=gender;
this.age=age;
}
public String toString() { //重写了toString方法
return "[" + name + "," + gender + "," + age + "]";
}
public static void main(String[] args) {
Person person=new Person("luka","man",21);
System.out.println(person);
}
}
/*
执行结果:
[luka,man,21]
*/