内部类

内部类

1.概念

在Java中,可以将一个类定义在另一个类里面或者一个方法里,这样的类称为内部类。

包括:

  • 成员内部类
  • 局部内部类
  • 匿名内部类
  • 静态内部类

2.成员内部类

成员内部类是最普通的内部类,它的定义为:位于另一个类的内部,示例:

class Person {
    private String name;
    public Person(){}
    public Person(String name) {
        this.name = name;
    }
    class Inner {
        //内部类
        public void say() {
            System.out.println("这是一个内部类");
        }
    }
}

特点:

  1. 成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。

  2. 如果成员内部类有和外部类同名的属性时,会发生隐藏现象,即默认的情况下访问的时成员内部类的成员。如果要访问外部类的方法或者成员,需要使用以下形式:

    • 外部类.this.成员变量
    • 外部类.this.成员方法
    /**
     * 测试类
     * @author 孟祥宽
     *
     */
    public class Test {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Person person = new Person("外部类");
    		person.say();
    		/*
    		 * 创建内部类对象
    		 */
    		Person.Student student = person.new Student("内部类");
    		student.say();
    //		Student student = new Student("直接引用内部类");// 这样写会报错 Student cannot be resolved to a type
    	}
    }
    
    /**
     * Person类
     * @author 孟祥宽
     *
     */
    public class Person {
    	private String name;
    	
    	public Person() {}
    	public Person(String name) {
    		this.name = name;
    	}
    	
    	
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	/*
    	 * 重写toString()
    	 */
    	@Override
    	public String toString() {
    		return "Person [name=" + name + "]";
    	}
    
    	/*
    	 * 重写equals()
    	 * */
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Person other = (Person) obj;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    
    	public void say() {
    		System.out.println(this.name + "____这是外部类的方法");
    	}
    
    	/*
    	 * 内部类
    	 */
    	public class Student {
    		private String name;
    		public Student() {}
    		public Student(String name) {
    			this.name = name;
    		}
    		public void say() {
                /*调用外部类的成员变量
                外部类.this.成员变量(方法)
                */
    			System.out.println(this.name + "____这是内部类的方法;" + Person.this.name + ":这是外部类的名字");
    		}
    	}
    }
    
    

3.局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问权限仅限于方法内或者该作用域内。

示例:

package com.kaikeba.demo2;

import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class Demo2 {
	public static void main(String[] args) {
		Frame f = new Frame("QQ登录器");
		f.setVisible(true);
		f.setSize(300, 200);
		class MyWindowListener implements WindowListener{

			@Override
			public void windowOpened(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void windowClosing(WindowEvent e) {
				// TODO Auto-generated method stub
				f.setVisible(false);
			}

			@Override
			public void windowClosed(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void windowIconified(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void windowDeiconified(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void windowActivated(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}

			@Override
			public void windowDeactivated(WindowEvent e) {
				// TODO Auto-generated method stub
				
			}
			
		}
		MyWindowListener l = new MyWindowListener();
		f.addWindowListener(l);
	}
}

运行结果:image-20211125150117575

※注意:

局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。只能访问final型的局部变量

示例:

/**
 * 局部内部类
 * @author 孟祥宽
 *
 */
public class Demo {
	public static void main(String[] args) {
		int a = 5;// <=>final int a = 5;
		//a = 15;
		/*
		报错信息:Unresolved compilation problem: 
	Local variable a defined in an enclosing scope must be final or effectively final
		*/
		
		class Person {
			public void say() {
				System.out.println("这是局部内部类" + a);// .java文件会单独编译成编译成.class文件 会备份使用的变量a,这里的a是备份的10行的a 如果10-17行更改a的值会报错
			}
		}
		Person p = new Person();
		p.say();
	}
}

局部内部类会编译成单独的一个.class文件。

image-20211130144859932

4.匿名内部类

匿名内部类没有名字。编写时创建一次对象。

创建格式:

new 父类构造器 (参数列表) {// 可以是类 也可以是接口
    //匿名内部类的类体部分
}

示例:

/**
 * 匿名内部类
 * @author 孟祥宽
 *
 */
public class Demo3 {
	public static void main(String[] args) {
		Person p = new Person () {// person 接口的实现类

			@Override
			public void say() {
				// TODO Auto-generated method stub
				System.out.println("这是匿名内部类");
			}
			
		};
		p.say();
	}
}
/**
 * 接口
 * @author 孟祥宽
 *
 */
public interface Person {

	public void say();
}
 

运行结果:image-20211130142718044

4.1 特点:

  1. 使用匿名内部类时,必须是继承一个类或者一个接口,但是两者不可兼得,同时也只能继承一个类或者实现一个接口。
  2. 匿名内部类中是不能定义构造函数的。
  3. 匿名内部类中不能存在任何的静态成员变量和静态方法。
  4. 匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效。
  5. 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
  6. 只能访问final型的局部变量

5.静态内部类

/**
 * 外部类
 * @author 孟祥宽
 *
 */
public class Book {
	private static String name = "这个是外部类的属性";
	/**
	 * 静态内部类
	 * @author 孟祥宽
	 *
	 */
	static class Info{
		public void say() {
			System.out.println("这是一个内部类" + ":" + name);// 静态内部类只能使用静态变量
		}
	}
}

/**
 * 测试类
 * @author 孟祥宽
 *
 */
public class Demo {
	public static void main(String[] args) {
		Book.Info info = new Book.Info();// 创建内部类对象
		info.say();
	}
}

运行结果:image-20211130151044985

posted @ 2021-11-30 15:12  雨溟  阅读(43)  评论(0)    收藏  举报