内部类
成员内部类
可以直接在类的内部定义成员内部类
一般只会在类的内部自己使用
public class Person {
protected String name; //子类需要,但是外部不允许访问
protected int age;
protected String sex;
public class Inner {
public void test(int a,int b,String... strings) {
System.out.println(name); //内部类可以访问外部的成员变量
}
}
创造类
public static void main(String[] args) {
Person person = new Person();
Person.Inner inner = person.new Inner(); //在person里面创造Inner类
inner.test();
}
成员内部类也可以使用访问权限控制,如果我们我们将其权限改为private
,那么就像我们把成员变量访问权限变成私有一样,外部是无法访问到这个内部类的
变量的调用
public class Person {
protected String name = "outside"; //子类需要,但是外部不允许访问
protected int age;
protected String sex;
public class Inner {
String name = "inner";
public void test() {
System.out.println("方法的参数的name是 = "+name); //就近原则
System.out.println("成员内部类的name= "+this.name); //在内部类中使用this关键字,只能表示内部类的对象
System.out.println("成员内部类的name= "+Person.this.name); //要指定为外部对象,则需要在前面加上外部类名称
}
}
}
输出
方法的参数的name是 = inner
成员内部类的name= inner
成员内部类的name= outside
调用函数
public class Inner {
String name;
public void test(String name){
this.toString(); //内部类自己的toString方法
super.toString(); //内部类父类的toString方法
Test.this.toString(); //外部类的toSrting方法
Test.super.toString(); //外部类父类的toString方法
}
}
静态内部类
静态内部类就像静态方法和静态变量一样,是属于类的
创建方法
不需要依附于任何对象,可以直接创造静态内部类的对象
public static void main(String[] args) {
Person.Inner inner = new Person.Inner();
inner.test();
}
访问
静态内部类是无法访问到外部类的非静态内容的,受影响的只是外部内容的使用,内部不受影响,跟普通的类一样
原因:静态内部类属于外部类,不依附任何对象,如果直接访问外部类不知道应该访问哪个对象
public static class Inner {
String name;
public void test() {
System.out.println("我是静态内部类!"+name); //此时因为是内部类的所以就可以正确使用
}
}
局部内部类
类似于局部变量,在方法中创建
既然是在方法中说明的类,那么作用范围也就是在方法里
public void hello() {
class Inner { //类似于局部变量,先声明,后使用
public void test() {
System.out.println("我是局部内部类");
}
}
Inner inner = new Inner(); //局部内部类就直接使用类名就可以
inner.test();
}
匿名内部类
是局部内部类的简化版
在抽象和接口中都会含有某些抽象方法需要子类去实现,不能直接通过new的方法来创造一个抽象类或者是接口对象,但是可以使用匿名内部类
创建
public abstract class Workers {
public abstract void test();
}
抽象类使用
此时创建出来的Workers的对象,已经实现了抽象方法的抽象,这个抽象直接就定义好了,连名字都没有。就可以直接创造出对象
匿名内部类中同样可以使用类中的属性(因为它本质上就相当于是对应类型的子类)
public static void main(String[] args) {
Workers worker = new Workers() {
int a;
@Override
public void test() {
System.out.println("我是匿名内部类!");
}
};
worker.test();
}
接口使用
同样的,接口也可以通过这种匿名内部类的形式,直接创建一个匿名的接口实现类:
public static void main(String[] args) {
Study study = new Study() {
@Override
public void study() {
System.out.println("我是学习方法!");
}
};
study.study();
}
并不是只有抽象和接口才可以像这样创造匿名内部类,普通的类也可以,但是意义不大
Lambda表达式
创建一个临时的实现子类
条件:如果接口当中有且只有一个待实现的抽象方法,那么我们可以将匿名内部类简写成 Lambda表达式
标准格式为:([参数类型 参数名称,]...) ‐> { 代码语句,包括返回值 }
enum枚举
例如我们要为一个人设定一个状态,如果都是外部传入,则会不靠谱,因此不如自己内定
创建
可以为枚举类增加构造器、方法和字段
构造器只是在构造枚举常量的时候使用,且为私有,可以省略private 修饰符
public enum status { //enum表示是一个枚举类
RUNNING, STUDY, SLEEP; //后面的分号可以不打,建议打上
}
使用
private Status status; //类型变成刚刚定义的枚举类
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
如此,别人在使用的时候,就能直接清楚我们知道什么
枚举类型本质就是一个普通的类,但是它继承自Enum
类,我们定义的每一个状态都是 public static final
的status类型成员变量
//这里使用javap命令对class文件进行反编译得到 Compiled from "Status.java"
public final class com.test.Status extends java.lang.Enum<com.test.Status> {
public static final com.test.Status RUNNING;
public static final com.test.Status STUDY;
public static final com.test.Status SLEEP;
public static com.test.Status[] values();
public static com.test.Status valueOf(java.lang.String);
static {};
}
成员方法
既然枚举类型是普通的类,那么我们也可以给枚举类型添加独有的成员方法:
比较枚举类的值,可以直接使用==,而不需要equals()
public enum status { //enum表示是一个枚举类
RUNNING("跑步"), STUDY("学习"), SLEEP("睡觉"); //后面的分号可以不打,建议打上
private final String name;
status(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
使用
public static void main(String[] args) throws CloneNotSupportedException {
Workers workers =new Workers("x",12,"s");
workers.setStatus(Workers.status.SLEEP);
System.out.println(workers.getStatus().getName());
}
输出
睡觉
一些常用方法
Size.SMALL.toString();
Size s = Enum.valueOf(Size.class, “SMALL”);
//静态方法,返回包含全部枚举值的数组
Size[] values = Size.values();
//返回枚举常量在Enum声明中的位置,从0开始计数
int ordinal();
//出现在other之前,返回负数,相同位置则返回0,否则为正整数
int compareTo(E other);