在Java中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。
好比你设计类 B 的目的只是为了给类 A 使用,那么,我们就可将其设定为内部类,没有必要将类 B 设置成单独的 Java 文件,防止与其他类产生依赖关系.
成员内部类
如下,内部类可以访问外部类的成员变量,但是外部类不可以访问内部类的成员变量!!
public class Demo_1 {
public static void main(String[] args) {
Outter out = new Outter();
Outter.Inner in = out.new Inner();
in.show();
in.fun();
}
}
class Outter {
private int num = 5;
class Inner {
int tt = 2;
public void show() {
System.out.println(num);
}
public void fun() {
Inner in = new Inner();
in.show();
}
}
}
静态内部类
静态内部类不可以使用任何外部类的非static成员变量和方法,而内部类则都可以
public class Demo_1 {
public static void main(String[] args) {
Outter.Inner in = new Outter.Inner();
in.show();
in.fun();
}
}
class Outter {
private static int num = 5;
static class Inner {
public void show() {
System.out.println(num);
}
public void fun() {
Inner in = new Inner();
in.show();
}
}
}
局部内部类
局部内部类就是定义在方法中的类了,较少用
public class Demo_1 {
public static void main(String[] args) {
Outter out = new Outter();
out.fun();
}
}
class Outter {
public void fun() {
class Inner {
public void show() {
System.out.println("hello world");
}
}
Inner in = new Inner();
in.show();
}
}
匿名内部类
匿名内部类是为了简化实现接口的写法.lambda是为了进一步简化写法.并无别的高深之处.
一般情况下实现一个方法时如下的
public class Demo_2 {
public static void main(String[] args) {
Test test =new Test();
test.show();
}
}
interface inter{
void show();
}
class Test implements inter{
@Override
public void show() {
System.out.println("show");
}
}
为了简化书写,引入了匿名内部类
public class Demo_2 {
public static void main(String[] args) {
new inter() {
@Override
public void show() {
System.out.println("this is anonymous class");
}
}.show();
}
}
interface inter {
void show();
}
还可以进一步简化书写
public class Demo_2 {
public static void main(String[] args) {
((inter) () -> System.out.println("this is anonymous class")).show();
}
}
interface inter {
void show();
}
内部类的应用
以hadoop的MRAPPMaster类为例,其有多个内部类
以成员内部类 RunningAppContext为例,其成员变量不可以被外部类MRAPPMaster所访问到. 可以通过idea作图了解一个类的概况.
public class RunningAppContext implements AppContext {
private final Map<JobId, Job> jobs = new ConcurrentHashMap<JobId, Job>();
private final Configuration conf;
private final ClusterInfo clusterInfo = new ClusterInfo();
private final ClientToAMTokenSecretManager clientToAMTokenSecretManager;
public RunningAppContext(Configuration config) {
this.conf = config;
this.clientToAMTokenSecretManager =
new ClientToAMTokenSecretManager(appAttemptID, null);
}
@Override
public ApplicationAttemptId getApplicationAttemptId() {
return appAttemptID;
}
@Override
public ApplicationId getApplicationID() {
return appAttemptID.getApplicationId();
}
@Override
public String getApplicationName() {
return appName;
}
@Override
public long getStartTime() {
return startTime;
}
@Override
public Job getJob(JobId jobID) {
return jobs.get(jobID);
}
@Override
public Map<JobId, Job> getAllJobs() {
return jobs;
}
@Override
public EventHandler getEventHandler() {
return dispatcher.getEventHandler();
}
@Override
public CharSequence getUser() {
return this.conf.get(MRJobConfig.USER_NAME);
}
@Override
public Clock getClock() {
return clock;
}
@Override
public ClusterInfo getClusterInfo() {
return this.clusterInfo;
}
@Override
public Set<String> getBlacklistedNodes() {
return ((RMContainerRequestor) containerAllocator).getBlacklistedNodes();
}
@Override
public ClientToAMTokenSecretManager getClientToAMTokenSecretManager() {
return clientToAMTokenSecretManager;
}
@Override
public boolean isLastAMRetry(){
return isLastAMRetry;
}
@Override
public boolean hasSuccessfullyUnregistered() {
return successfullyUnregistered.get();
}
public void markSuccessfulUnregistration() {
successfullyUnregistered.set(true);
}
public void resetIsLastAMRetry() {
isLastAMRetry = false;
}
@Override
public String getNMHostname() {
return nmHost;
}
}