Java|内部类
- 内部类 :在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
一、成员内部类
- 成员内部类时最普通的内部类,定义在另一个类的内部
- 示例代码1:
//成员内部类的定义
public class Outer{
private String name = "全辣柯基";
public class Inner{
private static final String Welcome = "HelloWorld";
private String say = "芜湖";
public void sayHello(){
System.out.println(say);
}
}
}
//成员内部类的调用
public class Test{
public void main(String[] args){
//创建外部类对象
Outer outer = new Outer();
//创建内部类对象
Inner inner = outer.new.Inner();
inner.say();
}
}
- 示例代码2:同名属性和方法的调用
//成员内部类的定义
public class Outer{
private String name = "全辣柯基";
private int age = 10;
public class Inner{
private String name = "全辣鲤鱼";
private int age = 20;
void say(){
System.out.println(name); //会输出 全辣鲤鱼,若同名默认优先内部类。
System.out.println(age); //会输出20
System.out.println(Outer.this.name); //输出全辣柯基
System.out.println(Outer.this .age); //输出10
System.out.println(this.name); //输出全辣鲤鱼
System.out.println(this.age); //输出20
}
}
}
//调用 -> 展示创建内部类对象的语法
public class Test{
public void main(String[] args){
//创建内部类的另一种语法
Inner inner = new Outer().new Inner();
inner.say;
}
}
- 注意事项:
- 创建内部类对象的语法有两种
-
先创建外部类对象,再创建内部类对象
Outer outer = new Outer()
Inner inner = outer.new Outer(); -
合并创建
Inner inner = new Outer().new Inner();
- 内部类中不能定义静态成员变量和静态方法,但可以定义static finnal,即静态常量
二、静态内部类
-
静态内部类与成员内部类的定义只在于类名前加了static修饰词
-
区别在于初始化静态内部类和调用静态内部类的属性和方法
-
示例代码:
public static class Outer{
private String name = "全辣柯基";
private int age = 18;
public static class Inner{
private String name = "全辣鲤鱼";
private int age = 22;
public static String welcome = "Hello"; // 静态内部类中可以定义静态变量和静态方法
public void show{
//1.调用外部类的属性
//先创建外部类的对象
Outer outer = new Outer();
//再调用外部类属性
System.out.println(outer.name);
System.out.println(outer.age);
//2.调用静态内部类的属性和方法
System.out.println(name);
System.out.println(age);
//3.调用静态内部类的静态属性
//静态成员通过类名访问
System.out.println(Inner.welcome);
}
}
}
-> 测试代码
public void main(String[] args){
//*****由于静态类和外部类时平级的,所以不需要先创建外部类
//*****直接创建静态内部类对象
Outer.Inner inner = new Outer.Inner(); //注意,new后面的Outer后无括号,真正new的时Inner,Outer只表示一种包含关系
inner .show();
}
- 注意事项:
- 只有静态内部类可以用static修饰,正常的类不可以用static修饰
- 静态内部类和外部类是平级的,所以可以直接创建静态内部类的对象,而不要先创建外部类对象。
- 静态变量可以通过类名.来调用
- 静态内部类中可以定义静态变量
三、局部内部类
- 局部内部类定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
- 示例代码1:局部内部类的定义和访问
public class Outer{
private String name = "全辣柯基";
private age = 18;
public void show(){
private String address = "重庆";
//在外部类的方法里定义局部内部类
//局部内部类的定义不加修饰词
class Inner{
private String phone = "57575757";
private String email = "haoshuai@qq.com";
public void show2(){
//访问外部类的属性
System.out.println(Outer.this.name);
System.out.println(Outer.this.age);
//访问内部类的属性
System.out.println(this.phone);
System.out.println(this.email);
}
}
}
}
- 示例代码2:当定义局部内部类的方法是静态方法时
public class Outer{
private String name = "全辣柯基";
private age = 18;
public static void show(){
private String address = "重庆";
//在外部类的方法里定义局部内部类
//局部内部类的定义不加修饰词
class Inner{
private String phone = "57575757";
private String email = "haoshuai@qq.com";
public void show2(){
//当show()方法为普通方法时,局部内部类的方法可以直接调用外部类的不重名属性。
//System.out.print(name);
//***当show()方法为静态方法时,不可以直接调用,因为静态方法不能直接访问非静态的属性,可以采取以下调用。
System.out.println(Outer.this.name);
System.out.println(Outer.this.age);
}
}
}
}
- 小结:
- 当存放局部内部类的方法是静态方法时,局部内部类的方法不能直接访问外部类的属性
- 为了清晰和不易出错建议所有的调用都加上如Outer.this,this等前缀。
- 示例代码3:如何 调用局部内部类的方法
//先定义一个局部内部类
public class Outer{
private age =18;
public void show(){
private String address = "重庆";//****如何访问address属性?
class Inner{
private String phone = "57575757";
private String email = "haoshuai@qq.com";
public void show2(){
public void show2(){
System.out.println(Outer.this.name);
System.out.println(Outer.this.age);
}
}
}
倘若想在主函数里创建Outer对象,通过调用 存放局部内部类的方法show 来达到调用show2的目的,是不行的
public void main(String[] args){
Outer outer = new Outer();
outer.show;
}
不会有任何输出,因为在执行Outer.show方法时里面 只初始化了一个变量phone,接着就是定义了一个局部内部类,但这个类没有得到使用。
所以如果想要使用show2方法的话,需要在方法里创建局部内部类对象,如
public class Outer{
private age =18;
public void show(){
private String address = "重庆";//定义局部变量
class Inner{
private String phone = "57575757";
private String email = "haoshuai@qq.com";
public void show2(){
System.out.println(Outer.this.name);
System.out.println(Outer.this.age);
}
}
//******创建局部内部类对象
Inner inner = new Inner();
inner.show2();
}
}
-> 这个时候再在主函数里调用就可以打印出show2方法了。
public void main(String[] args){
Outer outer = new Outer();
outer.show;
}
- 示例代码4:如何访问局部变量?即 存放局部内部类的方法 里定义的变量
public class Outer{
private age =18;
public void show(){
finnal private String address = "重庆";//定义局部变量
class Inner{
public void show2(){
//访问局部变量
//注意:jdk1.7及以上要求 访问的变量必须是常量finnal,jdk1.8以后,自动将变量添加为finnal,不再用手动定义
System.out.println(address);
}
}
}
}
- 注:为什么访问的局部变量必须是常量?
- 常量的特点是不可修改
- 方法中的变量在执行完后会消失
- 但new出来的inner对象和类不会消失
- 所以类和对象不可能调用一个已经消失的量,所以需要把局部变量定义为常量。
- 局部内部类中同样不能定义静态成员变量
四、匿名内部类
-
没有类名的局部内部类(一切特性与局部内部类相同)
-
必须继承一个父类或一个接口
-
匿名内部类实际上是把定义类,实现类,创建对象的语法合并,并且只能创建一个该类的对象
-
匿名内部类的优点是减少代码量,并且可以在定义一个类的同时对其进行实例化
-
匿名内部类的缺点是可读性较差
-
示例代码
//1.定义一个USB接口
public interface USB{
void service();
}
//2.定义一个Mouse类来实现接口
public class Mouse{
@Override
public void service() {
System.out.println("已连接电脑,鼠标开始工作...");
}
}
//3.测试1
public class USBTest {
public static void main(String[] args) {
//创建接口类型的变量
//多态
USB usb = new Mouse();
usb.service();//能够打印鼠标开始工作
class FengShan implements USB{
@Override
public void service() {
System.out.println("连接电脑成功,风扇开始工作...");
}
}
//使用局部内部类创建对象
USB usb1 = new FengShan();
usb1.service(); //同样能打印得出
}
}
我们发现,这个风扇的局部内部类只使用一次后续就不再使用了;于是用匿名内部类对这种写法进行优化
//测试2
public class USBTest {
public static void main(String[] args) {
//使用匿名内部类进行优化(相当于创建了一个局部内部类)
USB usb = new USB(){
@Override
public void service() {
System.out.println("连接电脑成功,风扇开始工作了...");
}
};
usb.service();
}
这样使用一次后匿名内部类就不再使用。
- new后面可以是抽象类,父类,接口等。