java类和对象——内部类和对象的打印

240 阅读6分钟

1.内部类

可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。

public class OutClass {
    public class InnerClass {
        // OutClass是外部类
        // InnerClass是内部类
    }
}

【注意事项】

  • 定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类。
  • 内部类和外部类共用同一个java源文件,但是经过编译之后,内部类会形成单独的字节码文件。
public class OutClass {

}

class Work {
    
}
// OutClass 和 Work 是两个独立的类

1.1 内部类的分类

  • 实例内部类(未被static修饰的成员内部类)
  • 静态内部类(被static修饰的成员内部类)
  • 局部内部类
  • 匿名内部类
public class OutClass {
    //成员位置定义:未被static修饰 -》 实例内部类
    public class InnerClass {
        
    }
    //成员位置定义:被static修饰 -》 静态内部类
    static class Work {

    }
    
    //也可以在方法中定义类 -》 局部内部类 -> 几乎不使用
    public void func() {
        class func2 {
            
        }
    }
}

1.2 内部类

1.2.1 实例内部类

未被static修饰的成员内部类。

  1. 如何获取实例内部类的对象?

【方式】:

// OutClass.InnerClass innerClass = outClass.new InnerClass();
public class OutClass {
    public int a = 10;
    public String ch = "#######";
    public static int b = 20;

    public void printOut() {
        System.out.println("I Love China!!!");
    }
    /*
    * 实例内部类
    * 1. 如何获取实例内部类的对象?
    */
    class InnerClass {//内部类
        public int day = 12;
        public String tele = "193 8979 0399";
        public  static final int age = 19;

        public void printIn() {
            System.out.println("I Love Java!!!");
        }
    }
    
    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        OutClass.InnerClass innerClass = outClass.new InnerClass();
        System.out.println("外部类ch:" + outClass.ch);
        System.out.println("外部类a:" + outClass.a);
        System.out.println("内部类tele:" + innerClass.tele);
        System.out.println("内部类age:" + innerClass.age);
    }
}

【解释】

 OutClass.InnerClass innerClass = outClass.new InnerClass();

通过外部类 . 内部类找到内部类,然后再创建一个变量;再通过外部类对象的引用(outClass). new上一个内部类的对象。


还有一种写法是:

OutClass.InnerClass innerClass = new OutClass().new InnerClass();

【注】:这两种方式是一样的,但是我觉得上面那一种更容易理解。

  1. 实例内部类当中不能有静态成员变量。

代码报错

image.png



【分析】:

static是类加载的时候加载的,static的执行时机较靠前,先执行static,后执行内部类;在执行static的时候内部类还未加载,相当于内部类不存在。


给静态成员变量加上final:

public  static final int age = 19;

发现无报错

image.png

加上final之后,age就是一个常量了,编译的时候就确定了这个地方就是10。


【final的演示】:

image.png


final 把变量A变成了常量,而常量是不能修改的,final 修饰的常量一般是大写。

【注意事项】

  • 外部类中的任何成员都可以在实例内部类方法中直接访问。
  • 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束。
  • 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须外部类名称.this.同名成员 来访问。
  • 实例内部类对象必须在先有外部类对象前提下才能创建。
  • 实例内部类的非静态方法中包含了一个指向外部类对象的引用。
  • 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。


3. 在实例内部类当中,如何访问外部类相同的成员变量?

调用printIn函数

public class OutClass {
    public int a = 10;
    public String b = "#######";
    public static int c = 20;

    public void printOut() {
        System.out.println("I Love China!!!");
    }
    
    class InnerClass {//内部类
        public int day = 12;
        public String tele = "193 8979 0399";
        public  static final int age = 19;

        public void printIn() {
            System.out.println("I Love Java!!!");
            System.out.println(a);
            System.out.println(b);
            System.out.println(c);
            System.out.println(day);
            System.out.println(tele);
            System.out.println(age);
        }
    }

    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        OutClass.InnerClass innerClass = outClass.new InnerClass();
        innerClass.printIn();
    }
}

image.png


实例内部类和外部类的成员变量相同时,实例内部类优先。

public class OutClass {
    public String ch = "外部类优先";

    public void printOut() {
        System.out.println("I Love China!!!");
    }
    /*
    * 实例内部类
    * 1. 如何获取实例内部类的对象?
    */
    class InnerClass {//内部类
        public String ch = "实例内部类优先";

        public void printIn() {
            System.out.println(ch);
        }
    }

    public static void main(String[] args) {
        OutClass outClass = new OutClass();
        OutClass.InnerClass innerClass = outClass.new InnerClass();
        innerClass.printIn();
    }
}

image.png


那在实例内部类当中,如何访问外部类相同的成员变量呢?


方法1:

 public void printIn() {
     OutClass outClass = new OutClass();
     System.out.println(outClass.ch);
     System.out.println(ch);
 }

方法2:

 public void printIn() {
     OutClass outClass = new OutClass();
     System.out.println(OutClass.this.ch);
     System.out.println(ch);
 }

1.2.2 静态内部类

  1. 如何获取静态内部类对象?
public class OutClass2 {
    public int day = 12;
    int age = 19;
    public static String tele = "193 8979 0399";

    public void printOut() {
        System.out.println("I Love China!!!");
    }

    /*
    * 1.如何获取静态内部类对象?
    *
    */
    static class Innerclass2 {
        public int a = 10;
        int b = 20;
        public static String c = "*****";

        public void printIn() {
            System.out.println("I Love Java!!!");
        }
    }

    public static void main(String[] args) {
        OutClass2.Innerclass2 innerclass2 = new   OutClass2.Innerclass2();
    }
}
  1. 静态内部类中不能访问外部类的非静态成员。

代码报错

image.png

外部类的非静态成员,需要外部类对象的引用才能访问。


如果非要访问呢?

【方法】:

 public void printIn() {
     OutClass2 outClass2 = new OutClass2();
     System.out.println(outClass2.day);
     System.out.println(outClass2.age);
     System.out.println(tele);
 }

【注意事项】

  • 在静态内部类中只能访问外部类中的静态成员。

  • 创建静态内部类对象时,不需要先创建外部类对象。

1.3 局部内部类

局部内部类:定义在方法体内部

public class OutClass2 {
    public void func() {
        class test {
            //局部内部类
        }
    }
}

几乎不会用到,所以简单了解就可以了。


【注意事项】

  • 局部内部类只能在所定义的方法体内部使用。
  • 不能被public、static等修饰符修饰。
  • 编译器也有自己独立的字节码文件,命名格式:外部类名字$内部类名字.class。
  • 几乎不会使用。

1.4 匿名内部类

后序讲抽象类和接口时给大家详细介绍。

class Test1 {
    public int age = 19;
    public String name = "zhangsan";
}

public class Person {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        System.out.println(test1.age);
        System.out.println(test1.name);

        //匿名对象只能使用一次,所以每次使用都要重新new一下
        System.out.println(new Test1().age);
        System.out.println(new Test1().name);

        new Test1() {
            //匿名内部类
        };
    }
}

2. 对象的打印

class Test1 {
    public int age = 19;
    public String name = "zhangsan";

    public void show() {
        System.out.println("姓名:" + name + "年龄:" + age);
    }
}

public class Person1 {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        test1.show();
    }

image.png

如果要输入的信息比较多,那就需要一个一个的书写,这样比较麻烦,在java中还有一种更快的输出方式。

使用**toString()**输出。


步骤:

  1. 鼠标放到show方法,右击鼠标,出现以下对话框。

image.png

2.点击Generate...,出现以下对话框。

image.png

  1. 在出现的对话框单击toString()后,出现以下对话框并点击OK。

image.png

class Test1 {
    public int age = 19;
    public String name = "zhangsan";

    @Override
    public String toString() {
        return "Test1{" + "age=" + age + ", name='" + name + '\'' + '}';
    }

    public void show() {
        System.out.println("姓名:" + name + "年龄:" + age);
    }
}

public class Person1 {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        test1.show();
    }

image.png

@Override 是一个注解,用来充当这一个检查的作用,不写也不会有影响。