Java 内部类详解
- 1 内部类概述
- 2 成员内部类语法
- 3 通过成员内部类解决多继承
- 4 静态内部类语法
- 5 通过静态内部类代替有参构造
- 6 局部内部类
- 7 匿名内部类
1 内部类概述
内部类大致分为:成员内部类、静态内部类、局部内部类、匿名内部类
public class A {
//定义成员内部类
class B1 {}
//静态内部类
static class B2{}
void method1() {
//局部内部类
class B3{}
}
}
2 成员内部类语法
为什么要使用成员内部类?
(1)、有时需要使用成员内部类来表示一个数据结构
(2)、可以使用内部类来结局类的多继承问题
成员内部类特点
(1)、内部类编译后是单独的一个字节码文件
(2)、文件名是 Outer$Inner.class
(3)、成员内部类和成员变量、成员方法一样是属于某一个外部类对象的
(4)、内部类一般只在外部类的类体中使用,不在外部使用
(5)、成员内部类可以定义实例变量、实例方法、不能定义静态成员,因为成员内部类是属于某个外部类对象,而静态成员和对象没有任何关系。
(6)、成员内部类中可以使用外部类的实例成员
(7)、成员内部类可以加访问权限修饰符
public class Outer {
//成员变量
int xx = 10;
public void m1(){
System.out.println("实例方法可以直接使用成员变量xx " + xx);
}
class Inner{
int yy = 20;
public void innerM1() {
System.out.println("成员内部类的实例方法");
//使用外部类的实例成员
System.out.println("使用外部类的实例成员xx " + xx);
}
//成员内部类中不能定义静态成员
//static int zz;
}
}
package Innerclass;
//导入内部类
import Innerclass.Outer.Inner;
public class Test01 {
public static void main(String[] args) {
//通过对象访问实例成员
Outer outer = new Outer();
System.out.println(outer.xx);
outer.m1();
//使用成员内部类创建对象
Outer.Inner inner = outer.new Inner();
//也可以导入,一般不这样写,因为可读性差,不知道这是一个内部类
Inner inner1 = outer.new Inner();
}
}
3 通过成员内部类解决多继承
OuterA类有一个方法methodA( )
OuterB类有一个方法methodB( )
Son类继承OuterA类,就自动拥有methodA( )方法如果还拥有methodB( ),可以定义一个内部类,让内部类继承OuterB类。
class OuterA {
public void methodA(){}
}
class OuterB {
public void methodB(){}
}
class Son extends OuterA{
//1.在子类中定义一个内部类继承
private class Inner extends OuterB{}
//2 定义一个内部类对象
private Inner inner = new Inner();
//3 定义一个方法和methodB方法签名相同
public void methodB(){
inner.methodB();
//因为只使用一次
new Inner().methodB();
}
}
class Test02{
public static void main(String[] args) {
Son son = new Son();
son.methodA();
//son的methodB方法,方法体是通过内部类对象调用的
son.methodB();
}
}
4 静态内部类语法
(1)、使用static修饰的成员内部类就是静态内部类
(2)、在静态内部类中不能访问外部类的非静态成员,可以直接访问外部类的静态成员
(3)、在静态内部类中可以定义静态成员
public class Outer {
//成员变量
int xx = 10;
//静态变量
static int oo = 20;
public static void sMethod(){
System.out.println("静态方法可以使用静态变量 oo " + oo);
//在外部类的静态方法中可以使用静态内部类
Inner obj = new Inner();
//静态方法中不能使用成员内部类
//Inner2 inner2 = new Inner2();
}
static class Inner{
int xx = 10;
public void innnerMethod(){
System.out.println("静态内部类的实例方法");
//在静态内部类中不能访问外部类的非静态成员,可以直接访问外部类的静态成员
System.out.println(oo);
}
//静态内部类中定义静态变量
static int ss = 20;
public static void staticInnerMethod(){
System.out.println("静态内部类的静态方法");
}
}
class Inner2{}
}
public class Test01 {
public static void main(String[] args) {
//通过类名访问它的静态成员
System.out.println("oo==" + Outer.oo);
Outer.sMethod();
//通过静态内部类创建对象
Outer.Inner inner = new Outer.Inner();
}
}
5 通过静态内部类代替有参构造
一般在实体类中,将字段私有化,提供对外的setter和geeter方法,只提供无参构造.因为,有参构造会破坏类的封装性,例如new Person(“zhnsgan”,1000,‘m’);一个人的年龄不可能为1000
public class Person {
private String name;
private int age;
private char sex;
public Person(){}
//通过静态内部类代替类的有参构造
public static class Bulider{
//1 创建和外部类相同的字段
private String name;
private int age;
private char sex;
//2 提供变种的seeter方法
public Bulider setName(String name) {
this.name = name;
return this;
}
public Bulider setAge(int age) {
this.age = age;
return this;
}
public Bulider setSex(char sex) {
this.sex = sex;
return this;
}
//3 提供公共的方法,返回外部类对象
public Person bulider(){
return new Person(this);
}
}
//4 定义一个外部类的构造方法,参数是内部类对象,把内部类对象的各个属性值赋值给外部类对象
public Person(Bulider bulider) {
this.age = bulider.age;
this.name = bulider.name;
this.sex = bulider.sex;
}
//省略seeter方法和getter方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
*/
public class Test01 {
public static void main(String[] args) {
Person person = new Person();
//如果没有重写toString()方法那么打印一个对象是 这个对象的完整类名+哈希码的十六进制
//静态内部类对象 . 方法
Person person2 = new Person.Bulider().bulider();
System.out.println(person2);
person2 = new Person.Bulider().setName("张三").setAge(16).setSex('m').bulider();
System.out.println(person2);
}
}
6 局部内部类
(1)、局部内部类不能加访问权限修饰符
(2)、局部内部类的作用域:从定义局部类的位置开始,到包含它的大括号位置结束
public class Outer {
public void m1(){
//定义局部变量
int x = 1;
//定义局部内部类
class Inner{}
Inner inner = new Inner();
}
}
7 匿名内部类
匿名内部类就是没有类名的内部类;
匿名类的定义和匿名内部类对象的创建是一起的
当某个成员内部类只使用一次时,就可以使用匿名内部类
public class Outer {
class Inner{}
}
public abstract class Animal {
//定义抽象类的抽象方法
public void speak(){};
}
public interface Flyabel {
void fly();
}
public class Test01 {
public static void main(String[] args) {
Outer outer = new Outer();
//创建成员内部类对象
outer.new Inner();
//以上两行可以写作一行
new Outer().new Inner();
//创建匿名内部类对象
new Outer(){
//大括号中的内容就是匿名内部类的类体
public void innereMethod(){
System.out.println("匿名内部类对象的类体");
}
};
//抽象类的引用需要赋值子类对象,当这个子类就只使用这一次时,就可以直接使用匿名内部类
//抽象类的引用可以指向匿名内部类对象,
// 在匿名内部类中对抽象类的抽象方法进行重写
Animal animal = new Animal() {
@Override
public void speak() {
System.out.println("狗在叫....");
}
};
animal.speak();
//接口的引用可以赋值匿名内部类对象
Flyabel flyabel = new Flyabel() {
@Override
public void fly() {
System.out.println("鸟在飞.....");
}
};
flyabel.fly();
}
}
public class Outer {
public int x = 88;
}
class Test01{
public static void main(String[] args) {
//普通类也可以赋值匿名内部来对象
Outer outer = new Outer() {
public void innerMehod() {
System.out.println("1111" + x);
}
};
//无法调用匿名内部类的方法,因为Outer类没有这个方法。
//outer.innerMehod();
//创建匿名内部类对象并调用匿名内部类的方法
new Outer() {
public void innerMehod() {
System.out.println("1111" + x);
}
}.innerMehod();
}
}