Java内部类与lambda表达式

本文深入探讨Java内部类的概念、用途及使用方式,包括内部类如何提高封装性、直接访问外部类私有数据的特点,以及非静态内部类和静态内部类的区别。此外,还介绍了匿名内部类的应用场景和Java 8对其的改进。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.为什么需要使用内部类

大部分的时候,类被定义成一个独立的程序单元。内部类就是把一个类放在另一个类的内部,包含内部类的类也被称为外部类。

内部类主要有以下作用:

a.内部类提供更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类.

b.内部类成员可以直接访问外部类私有数据,因为内部类被当做其外部类成员,同一个类的成员之间可以相互访问.但外部类不能访问内部类的实现细节,例如内部类的成员变量.

c.匿名内部类适合用于创建那些仅需要使用一次的类

内部类和外部类主要有两种区别

a.内部类比外部类多三个修饰符,private 、protected、static

b.非静态内部类不能拥有静态成员变量

2.非静态内部类

package com.liqiang.demo5;

public class InnerNoStatic {

    private class InnerClass{
        private int age = 1;
        public void show(){
            System.out.println(age);
        }
    }

}

非静态内部类不能含有静态成员

2.静态内部类

如果使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象。

静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。即使是静态内部类的实例方法也不能访问外部类的实例成员。
 

package innerclass;
 
public class StaticInnerClassTest {
	
	private int prop1 = 5;
	private static int prop2 = 5;
	
	static class StaticInnerClass{
		private static int age;
		
		public void accessOuterProp() {
			
		}
	}
 
}

3.使用内部类

分三种情况讨论内部类的用法

1.在外部类内部使用内部类:

在外部类内部使用内部类和平常使用普通的类没有什么区别,唯一的区别就是不要在外部类的静态成员(包括静态方法和静态初始块)中使用非静态内部类。

2.在外部类以外使用非静态内部类

如果希望在外部类以外的地方访问内部类(包括静态和非静态两种),则内部类不能使用private访问控制权限。

a.省略了访问控制符的内部类,只能被外部类或处于同一个包中的其他类访问。

b.使用了protected修饰的内部类,可被与外部类处于同一包中的其他类和外部类的子类所访问。

c.public修饰的内部类,可以在任何地方被访问。

变量语法的格式如下:

OuterClass.InnerClass varName

由于非静态内部类的对象必须寄生在外部类的对象里,因此创建非静态内部类对象之前,必须先创建其外部类对象。

OuterInstance.new InnerConstructor()

3.在外部类以外使用静态内部类

因为静态内部类是外部类类相关的,因此创建静态内部类对象是无需创建外部类对象。在外部类以外的地方创建静态内部类实例的如法如下:

new OuterClass.InnerConstructor();

4.Java8改进的匿名内部类

匿名内部类适合创建那些要一次使用的类

定义匿名内部类的语法如下:

    new 实现接口() | 父类构造器(实参列表)
    {
    //匿名内部类实体成分
    }

 

从上面定义可以看出匿名内部类必须继承一个父类,或实现一个接口,但最多只能继承一个父类和继承一个接口。

匿名内部类还有如下两条规则:

1.匿名内部类不能是抽象类,这个就不说了为什么了。。。

2.匿名内部类不能定义构造器。由于匿名内部类没名字啊,哥哥姐姐们,所以肯定不能有构造器啊。

如下是一个匿名内部类的简单用法:

   

package innerclass;
     
    interface Product{
        public double getPrice();
        public String getName();
    }
    public class AnnotmousTest {
        
        public void test(Product p) {
            System.out.println("buy a :" + p.getName() +" cost " + p.getPrice());
        }
        
        public static void main(String[] args) {
            AnnotmousTest ta = new AnnotmousTest();
            
            ta.test(new Product() {
                
                @Override
                public double getPrice() {
                    // TODO Auto-generated method stub
                    return 567;
                }
                
                @Override
                public String getName() {
                    // TODO Auto-generated method stub
                    return "hahaa";
                }
            });
        }
     
    }

当创建匿名内部类时就必须实现接口或抽象父类里的所有抽象方法。

在Java8之前,Java要求被局部内部类,匿名内部类访问的局部变量必须使用final修饰,从Java8这个就被取消了,如果局部变量被匿名内部类访问,那么该局部变量相当于自动使用了final.

如下

  

package com.liqiang.demo5;

interface A{
    void test();
}
public class InnerNoStatic {

    public static void main(String[] args){
        int age = 8;
        A a = new A() {

            @Override
            public void test() {
                // TODO Auto-generated method stub
                System.out.println(age);
            }
        };

        a.test();
        //加了这个会发生编译错误
        //age = 2;
    }
}

5.lambda表达式待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值