在类中定义的类
当类中的成员也是一种事物,可以把这个成员定义为内部类
分类:
1. 成员内部类
定义:成员内部类中静态的内容不能定义,除了静态常量
使用:
- 在成员内部类中可以直接使用外部类中的成员,包括私有的
- 使用内部类中的成员要通过内部类对象使用,包括私有的
- 其他类中使用内部类中的成员,需要通过外部类对象使用内部类成员
class OutClass{
double num= 0;
public OutClass(double num) {
this.num= num;
}
class InClass{ //内部类
public void show() {
System.out.println("In show");
}
}
}
不过要注意的是,当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
2. 静态内部类
定义:使用static修饰的内部类我们称之为静态内部类,静态内部类和非静态内部类之间存在一个最大的区别,非静态内部类在编译完成之后会隐含的保存着一个引用,该引用是指向创建它的外围类,但是静态类没有。
使用:
- 静态内部类的创建不需要依赖外部类可以直接创建。
- 静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。
class OutClass{
double num= 0;
public OutClass(double num) {
this.num= num;
}
static class InClass{ //内部类
public void show() {
System.out.println("In show");
}
}
}
3. 私有内部类
- 私有内部类中可以使用外部类中所有的内容,包括私有的
- 私有内部类只能在外部类中可以通过对象使用私有内部类中的私有内容,其他类中不能使用
public class PrivateInTest {
public static void main(String[] args) {
OutClass out = new OutClass();
out.outTest();
}
}
class OutClass{
public int a = 2;
private int b = 1;
private class InClass{
public int c = 0;
private int d = -1;
private void inTest() {
System.out.println("这是一个私有内部类方法");
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
void outTest(){
System.out.println("这是一个外部类成员方法");
InClass in = new InClass();
System.out.println(in.c);
System.out.println(in.d);
in.inTest();
}
}
4. 局部内部类
局部内部类也叫方法内部类顾名思义就是定义在方法里的类。
- 方法内部类不允许使用访问权限修饰符(public、private、protected)均不允许。
- 方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问 (换句话说其他方法或者类都不知道有这个类的存在)方法内部类对外部完全隐藏,出了创建这个类的方法可以访问它,其他地方均不能访问。
- 方法内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)
class People{
public People() {
}
}
class Man{
public Man(){
}
public People getWoman(){
class Woman extends People{ //局部内部类
int age =0;
}
return new Woman();
}
}
5. 匿名内部类
匿名内部类就是一个没有名字的方法内部类。
特点:
- 匿名内部类必须继承一个抽象类或者实现一个接口。
- 匿名内部类没有类名,因此没有构造方法。
Out.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
lambda:
为了简化大量的使用内部类对象,可以用Java8提供的lambda表达式
前提:函数型接口,只要一个必须要重写的抽象方法的接口
检查:注解@FunctionalInterface
语法:() -> {}
():抽象方法的参数列表
->:lambda符号,箭头符号
{}:重写抽象方法的方法体
注意:
- 需要指明引用类型 A a = () -> {}
- 如果lambda的方法体中只有一句,可以省去前后的{}
- 如果抽象方法有形参,参数类型可以省略
- 如果抽象方法有形参且只有一个,前后()可以省略
- 如果方法语句体只有一句且为return语句{}return可以省略
public class TreSetDemo {
public static void main(String[] args) {
// Set<User> s = new TreeSet();
Set<User> s = new TreeSet<>((o1, o2) -> o1.getUsername().compareTo(o2.getUsername()));//lambda匿名内部类作为参数传递
User u2 = new User("user1","pwd1");
User u5 = new User("user4","pwd4");
User u4 = new User("user3","pwd3");
User u6 = new User("user5","pwd5");
User u1 = new User("root","root");
User u3 = new User("user2","pwd2");
s.add(u1);
s.add(u3);
s.add(u4);
s.add(u2);
s.add(u5);
s.add(u6);
Iterator<User> i = s.iterator();
while(i.hasNext()){
System.out.println(i.next());
}
}
}