1.有名内部类
1)内部类定义:内部类是指在一个外部类内定义的类。
2)有名内部类:即该内部类有类名。
3)作用范围:全局有名内部类的使用方式类似于全局变量;局部有名内部类的使用方式类似局部变量——它们都有固定的使用范围。
public class Body {
public class Heart{//内部类的定义,类似于外部变量。
public void beat() {
System.out.println("正在跳动。。。。");
}
}
public static void main(String[] args) {
class Heart{//内部类的定义,类似于局部变量。无public修饰。作用范围是其所在的{}
public void beat() {
System.out.println("正在跳动。。。。");
}
}
Heart heart = new Heart();//可以直接创建对象。在另一个类中创建对象时,需要指明那个外部类中的内部类的对象
heart.beat();
}
}
注:内部类的修饰符可为public级别,即可以被外部类调用
2.匿名内部类
1)匿名内部类由于没有类名而不能单独存在,定义匿名内部类的同时须直接实例化该类,其语法格式如下:
new 父类构造器([参数列表])|接口(){
//匿名内部类类体
}
2)实质:普通类匿名内部类实质为普通类的子类。抽象类匿名内部类实质为抽象类的子类。接口匿名内部类实质为接口的实现类。
3)匿名内部类特点:
–匿名内部类一定是接口的实现类(该实现类仅能实现一个接口)或类(普通类或抽象类)的子类,其中new 关键字后面的类名或接口名即是该匿名内部类继承的父类或实现的接口;
–可以在匿名内部类中添加新的属性和方法,但是这些属性和方法不能被上转型对象所调用,只能被非上转型对象方式创建的匿名内部类对象所调用
import java.util.MissingFormatArgumentException;
public class Sea {
class Mammal {
public void move() {
System.out.println("正在移动......");
}
}
Mammal mammal = new Mammal("鲸鱼"){// 内部类的匿名内部类(相当于子类),往父类中传递参数。调用父类构造方法
int age = 100;//匿名内部类不须增加新的属性和方法,(无法通过上转型变量调用)
//匿名内部类一定不能是抽象类
void eat() {
System.out.println("正在吃饭");
}
@Override
void move() {
System.out.println("鲸鱼靠鳍移动......");
}
};
mammal.move();
创建对象时调用新增加的属性和方法。
new Mammal("鲸鱼"){
int age = 100;
void eat() {
System.out.println("正在吃饭");
}
@Override
void move() {
System.out.println("鲸鱼靠鳍移动......");
}
}.eat();
}
}
interface Mammal {
abstract void move();
}
public class Sea {
Mammal mammal = new Mammal() {//匿名内部类一定是接口的实现类(该实现类仅能实现一个接口)
@Override
public void move() {
System.out.println("鲸鱼靠鳍移动......");
}
};
public static void main(String[] args) {
Sea sea = new Sea();
sea.mammal.move();
}
}
–匿名内部类不能自定义构造方法,但是可以通过非静态代码块初始化成员变量;
–匿名内部类一定不能是抽象类;
import java.util.MissingFormatArgumentException;
public class Sea {
class Mammal {
public void move() {
System.out.println("正在移动......");
}
}
//匿名内部类
Mammal whale = new Mammal() {//调用Mammal中的无参构造方法
@Override
public void move() {
System.out.println("鲸鱼靠鳍移动......");
}
};
public static void main(String[] args) {
Sea sea = new Sea();
sea.whale.move();//whale 是内部类有其类名加点调用,whale是内部类名,move是whale子类的重写
}
}
3.静态内部类
1)定义:按照是否有static修饰分为静态内部类和非静态内部类,有static修饰的为静态内部类,没有static修饰的为非静态内部类。
2)分类:静态有名内部类和静态匿名内部类。
注意:如果为static内部类只能直接定义在外部类中。
静态匿名内部类如下;
class Father {
public void eat() {
System.out.println("筷子吃饭....");
}
}
/**
* 外部类
*/
public class OutClass {
/**
* 匿名内部类
*/
static Father son = new Father(){
@Override
public void eat() {
System.out.println(“叉子吃饭....");
}
};
}
静态有名内部类:
public class OutClass {
public static void main(String[] args) {
/**
* 静态有名内部类
*/
static class InClass {
public void printInfo() {
System.out.println("我是有名内部类");
}
}
}
}
注;静态内部类仅能直接访问外部类的静态成员变量和方法,可以通过创建外部类的对象间接使用非静态的成员变量和方法。
public class OutClass {
private double weight=72;
public static void print(String name) {
System.out.println(name);
}
static class InClass{
{
double weight = new OutClass().weight;//由于weight是非静态的,所以在静态内部类中使用时必须先创建外部类对象
print("Tom");//由于print方法为静态方法,所以可以直接使用。
}
}
}
3) 作用范围:在非外部类中定义的内部类和局部变量一样,其使用范围从定义的位置开始到其所在直接语句块结束。
public class OutClass {
public static void main(String[] args) {
if(args!=null) {
class InClass{
}
}
InClass inClass = new InClass();//无法创建对象,因为内部类作用范围无法作用到这里
}
}
4)特点:只有有名静态内部类中才允许有静态成员(静态属性、静态代码块和静态方法)。
4.内部类特点
1)内部类是一个独立的类:编译之后内部类会被编译成独立的.class文件,如果该内部类为有名内部类,则有名内部类字节码文件名为外部类的类名+
+
内
部
类
类
名
;
如
果
为
匿
名
内
部
类
,
则
匿
名
内
部
类
字
节
码
文
件
名
为
外
部
类
类
名
+
+内部类类名;如果为匿名内部类,则匿名内部类字节码文件名为外部类类名+
+内部类类名;如果为匿名内部类,则匿名内部类字节码文件名为外部类类名++数字;
2)普通外部类、抽象类和接口可以有内部类(匿名的或有名的);
3)内部类可以直接定义在类中,也可以定义在方法或代码块中;其中直接定义在外部类中的内部类可以有public、protected、默认的和private四种访问权限修饰(普通外部类、接口和抽象类只能使用public和default修饰),也可以使用static修饰( static不能修饰普通外部类、接口和抽象类);但是定义在方法或代码块中的内部类不能有访问修饰符修饰,也不能有static修饰。
4)内部类可以访问外部类的所有访问权限的成员变量。
public class Sea {
int b = 23;
static int c = 76;
static void print(){
System.out.println(new Sea().b);
}
static class Mammal{
{
print();
System.out.println(c);//内部类可以访问外部类的所有属性及方法。
}
static int age = 32;//只有有名静态内部类内才能有静态属性和方法}
}
6)在局部变量作用的范围内,如果定义的内部类需要使用该局部变量,则该变量必须有final修饰。(注:从 Java 8开始,如果定义的内部类需要使用该局部变量,则该变量可以不使用final修饰。)
public class Sea {
int b = 23;
static int c = 76;
static void print(){
System.out.println(new Sea().b);
}
static abstract class Mammal {//抽象内部类,
public Mammal(String name) {
System.out.println(name);
}
abstract void move();
}
protected class Whale{//内部类有四种权限但放在方法内部(局部变量)不加任何权限
int age = 3;
}
public static void main(String[] args) {//外部类只有public和有好的两种权限
if(true) {
//final int f = 12;
int f = 12;
class Son{
{
System.out.println(f);//java8以后局部内部类可以使用外部类的局部变量,java7以前外部局部变量要加final
}
}
new Son();
}