1.五大成员:属性、方法、构造方法、代码块、内部类。
2.定义:在一个类的里面,再定义一个类。
例:在A类的内部定义B类,B类就被称为内部类。
3.时机:当内部类表示的事物是外部类的一部分,且内部类单独出现没有任何意义时。
例:ArrayList的迭代器。
4.内部类的访问特点:
内部类可以直接访问外部类的成员,包括私有。
外部类要访问内部类的成员,必须创建对象。
5.练习:写一个Javabean类描述汽车。
属性:汽车的品牌,车龄,颜色,发动机的品牌,使用年限。
public class Car {
String carName;
int carAge;
String carColor;
public void show(Car this) {
//打印调用者车的名字
System.out.println(this.carName);
Engine e = new Engine();
System.out.println(e.engineName);
}
class Engine {
String engineName;
int engineAge;
public void show() {
//内部类可以直接访问外部类的成员,包括私有
System.out.println(engineName);
System.out.println(carName);
}
}
}
public class Test {
public static void main(String[] args) {
Car c = new Car();
c.carName = "宾利";
c.carAge = 1;
c.carColor = "粉色";
c.show();
}
}
6.内部类的分类:
1)成员内部类(了解)
1、写在成员位置的,属于外部类的成员。
2、成员内部类可以被一些修饰符所修饰,比如:private,默认,protected,public,static等。
3、在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量。
4、成员内部类如何创建对象:
方法一:当成员内部类被private修饰时,在外部类中编写方法,对外提供内部类的对象。
方法二:当成员内部类被非私有修饰时,直接创建对象。
格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
Outer.Inner oi = new Outer( ).new Inner( );
public class Car {//外部类
String carName;
int carAge;
int carColor;
//成员内部类:写在成员位置的,属于外部类的成员
class Engine {//成员内部类
String engineName;
int engineAge;
}
}
public class Outer {
private class Inner{
}
public Inner getInstance(){
return new Inner();
}
}
public class Test {
public static void main(String[] args) {
/*
* 获取成员内部类对象的两种方式
* 方法一:外部类编写方法,对外提供内部类对象
* 方法二:直接创建
* 格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
* 范例:Outer.Inner oi = new Outer().new Inner();
* */
//创建对象方式:
//类名 对象名 = new 类名();
//Student s = new Student();
//内部类若私有,则报错
//Outer.Inner oi = new Outer().new Inner();
Outer o = new Outer();
//Outer.Inner inner = o.getInstance();//私有所以报错
Object inner = o.getInstance();//多态
System.out.println(o.getInstance());//Outer$Inner@3b07d329
}
}
5、成员内部类如何获取外部类的成员变量
外部类成员变量与内部类成员变量重名时,在内部类如何访问?
System.out.println(Outer.this.变量名);
public class Outer {
private int a = 10;
class Inner {
private int a = 20;
public void show() {
int a = 30;
System.out.println(Outer.this.a);//10
System.out.println(this.a);//20
System.out.println(a);//30
}
}
}
public class Test {
public static void main(String[] args) {
//创建内部类的对象,调用show方法
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
2)静态内部类(了解)
1、静态内部类是一种特殊的成员内部类。
2、静态内部类只能访问外部类中的静态变量和静态方法,如果想要访问非静态的需要创建对象。
public class Car {//外部类
String carName;
int carAge;
int carColor;
static class Engine {//静态内部类
String engineName;
int engineAge;
}
}
3、创建静态内部类对象的格式:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
4、调用静态内部类中的方法:
调用非静态方法的格式:先创建对象,用对象调用。
调用静态方法的格式:外部类名.内部类名.方法名();
public class Outer {
int a = 10;
static int b = 20;
//静态内部类
//静态内部类也是成员内部类的一种
//静态内部类只能访问外部类中的静态变量和静态方法
static class Inner {
public void show1() {
System.out.println("非静态的方法被调用了");
//如果想要访问非静态的需要创建对象
Outer o = new Outer();
System.out.println(o.a);
System.out.println(b);
}
public static void show2() {
System.out.println("静态的方法被调用了");
//如果想要访问非静态的需要创建对象
Outer o = new Outer();
System.out.println(o.a);
System.out.println(b);
}
}
}
public class Test {
public static void main(String[] args) {
//创建静态内部类对象的格式:
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer.Inner oi = new Outer.Inner();
//访问非静态需要创建外部类对象
oi.show1();
//调用静态方法的格式(对象也可以调用但不提倡)
//外部类名.内部类名.方法名();
Outer.Inner.show2();
}
}
3)局部内部类(了解)
1、将内部类定义在方法里面,类似于方法里面的局部变量。
2、外界无法直接使用,需要在方法内部创建对象并使用。
3、该类可以直接访问外部类的成员,也可以访问方法内的局部变量。
public class Outer {
int b = 20;
public void show() {
int a = 10;
//局部内部类
class Inner {
String name;
int age;
public void method1() {
System.out.println(a);
System.out.println(b);
System.out.println("局部内部类中的方法method1");
}
public static void method2() {
System.out.println("局部内部类中的静态方法method2");
}
}
//创建局部内部类的对象
Inner i = new Inner();
System.out.println(i.name);
System.out.println(i.age);
i.method1();
Inner.method2();
}
}
public class Test {
public static void main(String[] args) {
Outer o = new Outer();
o.show();
}
}
4)匿名内部类(掌握)
1、匿名内部类本质上就是隐藏了名字的内部类。
2、可以写在成员位置,也可以写在局部位置。
3、格式(整体是一个类的子类对象或者接口的实现类对象):
new 类名或者接口名( ){ //继承\实现
重写方法; //方法重写
}; //创建对象new Inter() {
public void show () {
}
};
4、使用场景:
当方法的参数是接口或者类时,
以接口为例,可以传递这个接口的实现类对象。
如果实现类只使用一次,就可以用匿名内部类简化代码。
public abstract class Animal {
public abstract void eat();
}
public class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
public interface Swim {
public abstract void swim();
}
public class Test {
public static void main(String[] args) {
//匿名内部类
new Swim() {
@Override
public void swim() {
System.out.println("重写了游泳的方法");
}
};
new Animal() {
@Override
public void eat() {
System.out.println("重写了eat方法");
}
};
//应用:在测试类中调用method方法
/*第一种:写一个子类继承Animal类
再创建子类的对象,传递给method方法
Dog d = new Dog();
method(d);*/
//如果只用一次,单独定义一个类不合适
//第二种:匿名内部类
method(
new Animal() {
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
);
}
public static void method(Animal a) {//Animal a = 子类对象 多态
a.eat();//编译看左边,运行看右边
}
}
public class Test2 {
//是一个没有名字的成员内部类
Swim s = new Swim() {
@Override
public void swim() {
System.out.println("重写游泳方法");
}
};
public static void main(String[] args) {
//是一个没有名字的局部内部类
//Swim接口的实现类对象
//接口多态
Swim s = new Swim() {
@Override
public void swim() {
System.out.println("重写游泳方法");
}
};
//编译看左边,运行看右边
s.swim();
new Swim() {
@Override
public void swim() {
System.out.println("重写游泳方法");
}
}.swim();
}
}