内部类
任务列表
1. 什么内部类?
定义在一个类内部的类,成为内部类。
2.内部类有几种?
内部类:成员内部类(普通内部类),局部内部类,匿名内部类,静态内部类。
3.成员内部类
如何定义一个成员内部类?
需求:
- 定义一个Hero类,包含:name, hp, ap
- 在Hero中定义一个内部类,叫BattleScore,包含:kill,die, assit
public class Hero {
private String name; //英雄的名字
private int hp; //英雄的血量
private int ap; //英雄的攻击力
public class BattleScore{//内部类
private int kill;
private int die;
private int assit;
public int getKill() {
return kill;
}
public void setKill(int kill) {
this.kill = kill;
}
public int getDie() {
return die;
}
public void setDie(int die) {
this.die = die;
}
public int getAssit() {
return assit;
}
public void setAssit(int assit) {
this.assit = assit;
}
public BattleScore() {
super();
}
public BattleScore(int kill, int die, int assit) {
super();
this.kill = kill;
this.die = die;
this.assit = assit;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getAp() {
return ap;
}
public void setAp(int ap) {
this.ap = ap;
}
public Hero() {
super();
}
public Hero(String name, int hp, int ap) {
super();
this.name = name;
this.hp = hp;
this.ap = ap;
}
@Override
public String toString() {
return "Hero [name=" + name + ", hp=" + hp + ", ap=" + ap + "]";
}
}
普通内部类的使用
public class TestInnerClass {
public static void main(String[] args) {
Hero gailun = new Hero("盖伦", 500, 70);
Hero.BattleScore bs = gailun.new BattleScore(8, 0, 12);
}
}
问题:
-
成员内部类的访问修饰符可以有哪些?
public,protected,private以及默认。选哪个取决于需求。
-
成员内部类如何创建对象?
外部类类名.内部类类名 对象名 = 外部类对象.new 内部类类名(实参);
-
为什么要有成员内部类?
有些类只是和某些或某个类有关系,为了更好的组织代码,把一个类定义在了另外一个类里。
内部类可以直接访问外部类的成员(成员方法和成员属性)。
public class Hero {
private String name; //英雄的名字
private int hp; //英雄的血量
private int ap; //英雄的攻击力
public class BattleScore{
private int kill;
private int die;
private int assit;
public void test() {
System.out.println(name);
}
public void test2() {
name = "亚瑟";
}
public void test3() {
setName("怪僧");
}
public int getKill() {
return kill;
}
public void setKill(int kill) {
this.kill = kill;
}
public int getDie() {
return die;
}
public void setDie(int die) {
this.die = die;
}
public int getAssit() {
return assit;
}
public void setAssit(int assit) {
this.assit = assit;
}
public BattleScore() {
super();
}
public BattleScore(int kill, int die, int assit) {
super();
this.kill = kill;
this.die = die;
this.assit = assit;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getAp() {
return ap;
}
public void setAp(int ap) {
this.ap = ap;
}
public Hero() {
super();
}
public Hero(String name, int hp, int ap) {
super();
this.name = name;
this.hp = hp;
this.ap = ap;
}
@Override
public String toString() {
return "Hero [name=" + name + ", hp=" + hp + ", ap=" + ap + "]";
}
}
public class TestInnerClass {
public static void main(String[] args) {
Hero gailun = new Hero("盖伦", 500, 70);
Hero.BattleScore bs = gailun.new BattleScore(8, 0, 12);
bs.test3();
bs.test();
}
}
4.静态内部类
如何定义静态内部类
需求:
- 定义一个英雄类Hero,包括:name, hp, ap;
- 在Hero类内部定义一个静态内部类敌方水晶类EnemyCrystal, 包括:hp
public class Hero {
private String name; //英雄的名字
private int hp; //英雄的血量
private int ap; //英雄的攻击力
public static class EnemyCrystal{
private int hp = 10000;
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public void youWin() {
System.out.println("英雄停止攻击");
}
}
public Hero() {
super();
}
public Hero(String name, int hp, int ap) {
super();
this.name = name;
this.hp = hp;
this.ap = ap;
}
}
如何创建静态内部类对象
外部类类名.内部类类名 对象名 = new 外部类类名.内部类类名(实参);
public class Test {
public static void main(String[] args) {
Hero.EnemyCrystal ec = new Hero.EnemyCrystal();
}
}
为什么需要静态内部类?
它不像普通内部类,普通内部类是一个对象对应一个内部类对象。静态内部类是一个独立的个体。
拿敌方水晶为例,所有英雄公用一个水晶。地方水晶被摧毁之后,我方英雄都会赢。
package com.lanou.staticinnerclass;
public class Hero {
private static boolean gameOver = false;//游戏是否结束
private String name; //英雄的名字
private int hp; //英雄的血量
private int ap; //英雄的攻击力
public static class EnemyCrystal{
private int hp = 10000;
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public void youWin() {
System.out.println("英雄停止攻击");
test();
}
}
public void attack() {
if(gameOver == true) {
System.out.println("stop");
}else {
System.out.println("正常攻击");
}
}
public static void test() {
gameOver = true;
}
public Hero() {
super();
}
public Hero(String name, int hp, int ap) {
super();
this.name = name;
this.hp = hp;
this.ap = ap;
}
}
package com.lanou.staticinnerclass;
public class Test {
public static void main(String[] args) {
Hero.EnemyCrystal ec = new Hero.EnemyCrystal();
Hero h1 = new Hero("盖伦", 500, 70);
Hero h2 = new Hero("盲僧", 480, 80);
h1.attack();
h2.attack();
ec.youWin();
h1.attack();
h2.attack();
}
}
静态内部类只能访问外部类的静态方法和静态属性。
上述代码模拟的是:水晶被打烂,英雄停止攻击。
局部类(本地类) local class
局部变量指的是方法中定义的变量,局部类指的是方法中定义的类。
局部类的定义:
public class TestLocalClass {
public static void main(String[] args) {
class AA{
private int a;
public double b;
public void test() {
}
public AA(int a, double b) {
super();
this.a = a;
this.b = b;
}
}
AA a = new AA(100,25.8);
}
}
局部类不能使用public,protected,private等关键字。因为本身是局部,只能作用这个方法,作用不到这个包的其他类里,更作用不到其他包里。
局部类的声明周期很短,方法一结束,类就消失了。
局部类中可以使用方法内的变量,但是变量会被编译器定义为final类型。
匿名内部类
匿名内部类类是局部类的一种特殊形式。
匿名:就是没名字。
匿名类:没有名字的类。
问题:一个类,没有名字怎么创建对象?
正常创建一个对象的语法格式:类名 对象名 = new 类名(实参);
现在的问题是没有类名了,如何创建对象。
匿名类的用途
- 作为抽象类的子类。
- 作为接口的实现类。
匿名类作为抽象类的子类
假定有如下抽象类:
public abstract class Shape {
private int numberOfSide; //边数
public abstract double area(); //面积
public abstract double perimeter(); //周长
public int getNumberOfSide() {
return numberOfSide;
}
public void setNumberOfSide(int numberOfSide) {
this.numberOfSide = numberOfSide;
}
public Shape() {
super();
}
public Shape(int numberOfSide) {
super();
this.numberOfSide = numberOfSide;
}
@Override
public String toString() {
return "Shape [numberOfSide=" + numberOfSide + "]";
}
}
抽象类的正常用法: 定义一个子类,子类实现抽象类中没有实现的方法
public class Rectangle extends Shape {
private double width;
private double height;
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Rectangle() {
super(4);
}
public Rectangle(double width, double height) {
super(4);
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
@Override
public double perimeter() {
return 2 * (width + height);
}
}
使用的时候,创建子类对象,而不是抽象类对象。
使用匿名类完成抽象类尚未完成的功能:
public class Test {
public static void main(String[] args) {
Rectangle rect1 = new Rectangle(10, 8);
System.out.println(rect1.perimeter());
System.out.println(rect1.area());
int radius = 20;
Shape s = new Shape() {
@Override
public double area() {
return radius * radius * Math.PI;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
};
System.out.println(s.area());
System.out.println(s.perimeter());
int side = 8;
Shape s2 = new Shape() {
@Override
public double area() {
return side * side;
}
@Override
public double perimeter() {
// TODO Auto-generated method stub
return 4 * side;
}
};
System.out.println(s2.area());
System.out.println(s2.perimeter());
}
}
匿名类通常作为抽象类的子类。 抽象类之所以不能创建对象,是因为抽象类中有没有实现的方法。
如果实现了这些方法就可以正常创建对象了。例如:子类继承抽象类,实现抽象类中没有实现的方法。
再例如:匿名类实现抽象方法。
因为匿名类没有名字,所以使用起来比较怪异,它不能像普通类一样创建对象,也不能像普通类一样定义类(class 类名)。所以创建匿名类的语法比较怪异。
匿名类的创建和匿名类的对象的创建是一体的。
语法格式 new 抽象类类名(实参){ 实现抽象方法,以及定义属性以及方法 }
实际上定义属性和方法没有意义?因为定义完以后也没有办法调用。
匿名类的好处:可以不用新建一个文件(类)。
匿名类作为接口的实现类
假定有如下接口:
public interface CalculateInterface<X, Y, Z> {
public Z operator(X t1, Y t2);
}
正常情况下,要编写接口的实现类,实现类去实现接口中定义的方法。
public class Sum implements CalculateInterface<Integer, Integer, Integer> {
@Override
public Integer operator(Integer t1, Integer t2) {
return t1 + t2;
}
}
public class Test {
public static void main(String[] args) {
Sum s = new Sum();
int n = s.operator(100, 200);
System.out.println(n);
}
}
匿名类实现接口:
public class Test {
public static void main(String[] args) {
CalculateInterface<Integer, Double, Double> c = new CalculateInterface<Integer, Double, Double>() {
@Override
public Double operator(Integer t1, Double t2) {
return t1 - t2;
}
};
System.out.println(c.operator(123, 321.5));
}
}
匿名类本质上和实现类没有什么区别,都实现了接口中定义的方法。
唯一的区别就是,实现类有自己的名字,匿名类有没有类名。
匿名类实现接口的语法格式和 匿名类继承抽象类语法格式一样:
接口名 对象名 = new 接口名(){接口中的方法实现};
总结
成员内部类,静态内部类,局部内部类不用刻意去记。
匿名类必须要会,不会是不可能的,因为天天用。
匿名类往往用于接口!接口都是别人(系统)定义好的,我们所要做的事情就是通过匿名类创建对象。
匿名类作为抽象类的子类: 抽象类类名 对象名 = new 抽象类类名(实参){ 实现还抽象方法};
匿名类作为接口的实现类:接口名 对象名 = new 接口名(){实现接口中的方法};