内部类的定义:在java中,允许在一个类的内部定义类,称为内部类,这个内部类所在的类称为外部类。内部类定义在外部内的内部,通常只服务于外部类,对于其他外部是不具备可见性的。
内部类应用场景:1.当某个类只为一个类提供服务时,可以将这个类定义成内部类
2.可以解决接口或者抽象类不能实例化的问题
public class Demo0 {
public static void main(String[] args) {
//Aoo a=new Aoo();
// Hoo h=new Hoo();
Hoo h1=new Hoo() {
//重写接口的方法即可
@Override
public void test() {
}
};
}
}
abstract class Aoo{
}
interface Hoo{
public void test();
}
成员内部类:在一个类中除了可以定义成员变量,成年方法,还可以定义类,这样的类称为成员内部类。在成员内部类中可以访问外部类的所有成员资源(包括私有成员),例如成员变量和成员方法;在外部类中,同样可以访问成员内部类的变量和方法。
package day13;
//定义测试类
public class Test {
public static void main(String[] args) {
Outer outer =new Outer();//创建外部类对象
Outer.Inner inner =outer.new Inner();//创建内部类对象
inner.show1();//测试在成员内部类中访问外部类成员变量和方法
outer.test2();//测试在外部类中访问成员内部类变量和方法
}
}
//定义外部类Outer
class Outer {
int m=0;//定义外部类成员变量
void test1(){//定义外部类成员方法
System.out.println("外部类成员方法");
}
//定义内部类Inner
class Inner{
int n=1;
void show1(){//定义内部类方法,访问外部类成员变量和方法
System.out.println("外部类成员变量m="+m);
test1();
}
void show2(){//定义内部类成员方法
System.out.println("内部类成员方法");
}
}
void test2(){//定义外部类方法,访问内部类成员变量和方法
Outer.Inner inner =new Outer().new Inner();
System.out.println("内部类成员变量n="+inner.n);
inner.show2();
}
}
使用内部类需要注意的问题:
1.内部类可以直接调用外部类的属性和方法(包括私有的)
2.外部类要调用内部类的属性和方法,需要通过内部类的对象去调用
3.创建内部类对象格式: Outer.Inner in = new Outer().new Inner();等价于【Outer outer=new Outer(),Inner inner=outer.new Inner().】
4.当外部类和内部类的属性重名时,可以通过 :外部类.this.属性 来访问外部类的属性
当外部类和内部类的方法重名时,可以通过 :外部类.this.方法() 来访问外部类的方法
5.成员内部类,直接写在外部类里面,和成员属性和方法位置一样
6.成员内部类,是可以被继承的
7. 内部类可以继承 ,需要通过外部类去找到内部类
局部内部类:又称“方法内部类”,就是定义在某个局部范围中的类,它和局部变量一样,都是在方法中定义的,其有效范围只限于方法内部。 在局部内部类中,局部内部类可以访问外部类的所有成员变量和方法,而局部内部类中的变量和方法却只能在创建该局部内部类的方法中进行访问。
局部内部类的使用场景:若方法返回值是一个接口,在没有子类或者不知道子类的情况下, //在方法中创建一个局部内部类,其他地方不需要用,仅在方法中使用。
package day13;
public class Demo2 {
public static void main(String[] args) {
}
public Too test(){
// //若方法返回值是一个接口,在没有子类或者不知道子类的情况下,
// //在方法中创建一个局部内部类,其他地方不需要用,仅在方法中使用
class T implements Too{
@Override
public void sayHi(){
}
}
//返回实现Too的类T对象
return new T();
}
}
interface Too{
public void sayHi();
}
静态内部类:就是使用static关键字修饰的成员内部类。静态内部类只能访问外部类的静态成员,同时通过外部类访问静态内部类成员时,可以跳过外部内直接通过内部类访问静态内部类成员。
public class Demo07 {
public static void main(String[] args) {
Outer o=new Outer();//创建外部类对象
Outer.Inner oi=new Outer().new Inner();//创建内部类对象
Outer.StaticInner ois=new Outer.StaticInner();
}
}
class Outer{
int num=10;
class Inner{//非静态成员内部类
public void show(){
System.out.println("Inner"+num);
}
}
static class StaticInner{//静态成员内部类
public static int a;
}
public void method(){
//非静态方法可以创建静态或非静态的成员内部类对象 this
Inner i=new Inner();
StaticInner si=new StaticInner();
}
public static void say(){
//静态方法不可以直接创建非静态成员内部类
//Inner i=new Inner();
//静态方法可以直接创建静态成员内部类
StaticInner si=new StaticInner();
}
}
总结:
创建非静态内部类对象:外部类名.内部类名 对象名=外部类对象.内部类对象
eg:Outer.Inner oi=new Outer().new Inner();//创建非静态内部类对象
创建静态内部类对象:外部类名.内部类名 对象名=外部类对象.内部类对象eg:Outer.StaticInner ois=new Outer.StaticInner();
匿名内部类:在java中调用某个方法时,如果该方法的参数是一个接口类型,除了可以传入一个接口实现类作为参数,还可以使用匿名内部类实现接口来作为该方法的参数。匿名内部类其实就是没有名称的内部类,在调用含有接口类型参数的方法时,通常为了简化代码,我们不会创建一个接口的实现类作为方法参数传入,而是直接通过匿名内部类的形式传入一个接口类型参数,在匿名内部类中完成方法的实现。
创建匿名内部类的格式:
格式1: new 类名(){} 表示:创建了类的子类的对象(匿名内部类是 指定类名的子类)
格式2: new 接口(){} 表示: 表示创建了接口实现类的对象(匿名内部类是 指定接口的实现类)
匿名内部类的本质:是一个继承类该类或者实现了该接口的子类匿名对象
匿名内部类的前提:存在一个类或者接口,当需要创建类或者接口对象的时候
案例一:调用某个方法,方法参数为接口类型,使用匿名内部类
package day13;
//定义Animal接口
interface Animal {
void shout();
}
public class Demo3 {
public static void main(String[] args) {
String name="小花";
//定义匿名内部类作为参数传递给animalShout()方法
animalShout(new Animal() {
@Override
public void shout() {
//JDK8开始,局部内部类和匿名内部类可以访问非final的局部变量
System.out.println(name+"喵喵");
}
});
}
//定义静态方法animalShout(),接受接口类型的参数
public static void animalShout(Animal an){
an.shout();//调用传入对象an的shout方法
}
}
案例二:某个方法的返回值为接口类型,使用匿名内部类解决。
package day1023;
/*
匿名内部类
*/
public class Demo04 {
//解决接口或者抽象类不能实例化的问题/
public Eoo demo(){
//省去了创建类的操作,匿名内部类
//接口创建实现是为了重写接口中方法,那何不如直接创建的时候重写该方法
return new Eoo() {
@Override
public void EooTest() {
}
};
}
public Roo rtest(){
return new Roo();
}
}
class Roo{
}
interface Eoo{
public void EooTest();
}