1.内部类的概念
当一个事物的内部,还有一个部分需要一个完整的结构进行描述,这个内部的完整的结构又只为外部事物提供服务,那么这个内部的完整结构最好使用内部类。在Java中,可以将一个类定义在另一个类或者一个方法的内部,前者称为内部类,后者称为外部类。内部类也是封装的一种体现。
2.内部类的分类
public class outclass{ //实例内部类 public class Innerclass{ } //静态内部类 static class Innerclass{ } public void method(){ class{ //局部内部类 } } }
3.实例内部类的实现
package inner; class OuterClass{ public int data1 = 1; int data2 = 2; public static int data3 = 3; public void test(){ System.out.println("OuterClass::test()"); } /** * 实例内部类 * 1.如何获取实例内部类的对象 * OuterClass.InnerClass innerClass =outerClass.new InnerClass(); * 2.public static int data6为什么错 * 因为static是先加载后运行的,先执行了static才实例化对象呢 * 实例内部类不能有静态的成员方法或变量 * 咋就行了 * public static final int data6 = 10;就行了 * 他这里的final是指常量,常量是指在程序编译时确定的,一旦初始化就不进行修改了 *3.如何在实例内部类获取外部类,就外部类.this.什么什么 */ class InnerClass{ int data1 = 6; public int data4 = 4; int data5 = 5; public static final int data6 = 10; public void func(){ System.out.println("InnerClass::func()"); System.out.println(OuterClass.this.data1); System.out.println(data1); System.out.println(data2); System.out.println(data3); System.out.println(data4); System.out.println(data5); System.out.println(data6); } } } public class Test { public static void main(String[] args) { OuterClass outerClass = new OuterClass(); System.out.println(outerClass.data1); OuterClass.InnerClass innerClass =outerClass.new InnerClass(); } }
注意事项
1.外部类中的任何成员都可以在实例内部类方法中直接访问
2.实例内部类所处的位置与外部类成员位置相同,因此也受public,private等访问限定符的约束
3.在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须用:外部类名称.this.同名成员来访问
4.实例内部类对象必须在先有外部类对象前提下才能创建
5.实例内部类的非静态方法中包含了一个指向外部类对象的引用
6.外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
4.静态内部类的实现
kage inner; class Outerclass2{ public int data1 = 1; int data2 = 2; public static int data3 = 3; public void test() { System.out.println("Outer::test()"); } /** * 1.如何获取静态内部类对象 *Outerclass2.Innerclass2 innerclass2 = new Outerclass2.Innerclass2(); * 2.静态内部类当中,不能访问外部类的非静态成员,外部类的非静态成员, * 需要通过外部类的对象的引用才能访问 * Outerclass2 outerclass2 = new Outerclass2(); * System.out.println(outerclass2.data1); * */ static class Innerclass2{ public int data4 = 4; int data5 = 5; public static int data6 = 6; public void func(){ Outerclass2 outerclass2 = new Outerclass2(); System.out.println(outerclass2.data1); System.out.println(outerclass2.data2); System.out.println("out::func()"); /*System.out.println(data1); System.out.println(data2);*/ System.out.println(data3); System.out.println(data4); System.out.println(data5); System.out.println(data6); } } } public class Test2 { public static void main(String[] args) { Outerclass2.Innerclass2 innerclass2 = new Outerclass2.Innerclass2(); innerclass2.func(); }
注意事项
1.在静态内部类中只能访问外部类中的静态成员
实在想访问怎么做
Outerclass2 outerclass2 = new Outerclass2();
System.out.println(outerclass2.data1);
2.创建静态内部类对象时,不需要先创建外部类对象
6.局部内部类的实现(没啥用)
public class Test2 { public void func(){ class Inner{ public void test(){ System.out.println("局部内部类"); } } Inner inner = new Inner(); inner.test(); }
注意事项
1.局部内部类只能在所定义的方法体内部使用
2.不能被public,static等修饰符修饰
3.编译器也有自己独立的字节码文件,命名格式:外部类名字$内部类名字.class
4.几乎不会使用
7.匿名内部类
先了解匿名对象
class Person{ public int age; public String name; }
public static void main(String[] args) { /*uterclass2.Innerclass2 innerclass2 = new Outerclass2.Innerclass2(); innerclass2.func();*/ Person person = new Person(); System.out.println(person.age); System.out.println(person.name); new Person();//匿名对象 System.out.println(new Person().age); System.out.println(new Person().name);//匿名对象只能使用一次 }
匿名内部类
new Person(){ //匿名内部类 //在讲抽象类和接口的时候再详细说 }
8.对象的打印
最初的学习,我们可以这样实现
class Student{ String name; int age; public void show(){ System.out.println("姓名" + name + "--" + "年龄" + age); } } public class Test3 { public static void main(String[] args) { Student student = new Student(); student.show(); } }
但是这样的缺点就是如果东西太多,我们写的太麻烦。那我们可不可以直接这样
System.out.println(student);
他得出来的是这样的
inner.Student@b4c966a
简单的可以认为是一个地址
按住ctrl点println看其源码
public void println(Object x) { String s = String.valueOf(x); if (getClass() == PrintStream.class) { // need to apply String.valueOf again since first invocation // might return null writeln(String.valueOf(s)); } else { synchronized (this) { print(s); newLine(); } } }
再点ctrl看valueOf的源码
public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); }
再点ctrl看toString的源码
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
发现他调用的是Object的toSring,那么我们以后直接右键Generate,toSring
@Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; }
就可以这样,然后方法进行重写,最后直接sout他
package inner; class Student{ String name; int age; @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } public class Test3 { public static void main(String[] args) { Student student = new Student(); System.out.println(student); } }
@Override这个东西叫注解,就是帮你检查,你的重写的对错