内部类
类中的基本组成就是成员属性和方法,但是在任何语言中结构也是允许嵌套的,在类中定义其他的类,这样的类就称为内部类。
内部类基本概念
内部类是一个独立且完善的类结构,在一个类内部除了属性和方法外可以继续使用class定义内部类。
class Outer{
private String msg = "www.mldn.cn"; //私有成员属性
public void fun(){
// 普通方法
Inner in = new Inner(); //实例化内部类对象
in.print();
}
class Inner{
//在outer内部定义Inner类
public void print(){
print(Outer.this.msg);
}
}
}
main{
Outer out = new Outer(); //实例化外部类对象
out.fun(); //调用外部类中的方法
}
观察内部类结果并不难理解,设置可以说其结构与普通类一样清晰明了。那么为什么需要内部类这样的结构?
从整体结构上来讲内部类结构并不合理,所以内部类最大的缺陷在于破坏了程序的整体结构,但内部类仍有一定优势。
优势: 内部类可以轻松访问外部类中的私有属性。
内部类相关说明
现在所定义的内部类属于普通的内部类的形式,普通的类内部往往提供属性和方法。
需要注意的是,内部类虽然可以方便访问外部类中的私有成员或方法,同理外部类也可以轻松的访问内部类中的私有成员和方法。
class Outer{
private String msg = "www.mldn.cn"; //私有成员属性
public void fun(){
// 普通方法
Inner in = new Inner(); //实例化内部类对象
in.print();
print(in.info); //访问内部类的私有属性
}
class Inner{
//在outer内部定义Inner类
private String info = "good day"; //私有属性
public void print(){
print(Outer.this.msg);
}
}
}
使用内部类之后,内部类与外部类之间的私有操作的方法不再需要setter、getter以及其他间接方式完成,可以直接进行操作。
但是需要注意内部类本身也是一个类,虽然大部分情况下内部类往往是被外部类包裹的,但是外部依然可以产生内部类的实例化对象,此时格式如下:
外部类.内部类 内部类对象 = new 外部类().new 内部类();
内部类编译完成后自动形成“Outer I n n e r . c l a s s ” 类 文 件 , 其 中 “ Inner.class”类文件,其中“ Inner.class”类文件,其中“”这个符号换到程序中就变为了“.”,内外部类之间可以直接进行私有成员你的访问,这样一来内部类如果要是提供有实例化对象,一定要保证外部类已经实例化了。
如果此时Inner类只允许使用Outer类来使用,那么再这样的情况下就可以使用private进行私有定义。
private class Inner{
//在outer内部定义Inner类
private String info = "good day"; //私有属性
public void print(){
print(Outer.this.msg);
}
}
此时Inner类无法在外部进行使用。
Java中类作为最基础的结构体实际上还有与之类似的抽象类或者是接口,抽象类与接口中都可以定义内部结构。
interface IChannel{
public void send(IMessage msg);
interface IMessage{
//内部接口
public String getCon();
}
}
class ChannelImpl implements IChannel{
public void send(IMessage msg){
}
class MessageImpl implements IMessage{
public String getCon(){
}
}
}
main{
IChannel channel = new ChannelImpl();
channel.send(((ChannelImpl)channel).new MessageImpl());
}
内部抽象类可以定义在普通类、抽象类、接口内部。
interface IChannel{
public void send();
abstarct class AbstractMessage{
public abstarct String getCon();
}
}
class ChannelImpl implements IChannel{
public void send(){
AbstractMessage msg = new MessageImpl();
print(msg.getCon());
}
class MessageImpl extends AbstractMessage{
public String getCon(){
return "www.mldn.cn";
}
}
}
main{
IChannel channel = new ChannelImpl();
channel.send();
}
内部类中还有一些更为有意思的结果,即:如果现在定义了一个接口,那么可以在内部利用类实现该接口,JDK1.8之后追加了static方法可以不受实例化对象的控制,现在就可以利用此特性来完成功能。
接口内部进行接口实现
interface IChannel{
public void send();
class ChannelImpl implements IChannel{
public void send(){
print("www.mldn.cn");
}
}
public static IChannel getInstance(){
return new ChannelImpl();
}
}
main{
IChannel channel = IChannel.getInstance();
channel.send();
}
内部类十分灵活,只要语法满足,各种需求都可以帮你实现。
static定义内部类
如果现在内部类使用static定义,那么这个内部类就变为了外部类,static定义的结构独立于类之外,此时内部类结构相当于一个独立的程序类。
static定义的不管是类还是方法只能访问static成员,所以static定义的内部类只能访问外部类中的static属性。
class Outer{
private static final String MSG = "www.mldn.cn";
static class Inner{
public void print(){
print(Outer.MSG);
}
}
}
main{
Outer.Inner in = new Outer.Inner(); //实例化static内部类对象
}
此时Inner类是一个独立的类,想要实例化Inner类对象,只需要根据外部类.内部类 内部类对象 = new 外部类.内部类();
这个时候类名称带有“.”
static定义内部接口的形式最为常用。
interface IMessageWarp{
//消息包装
static interface IMessage{
public String getCon();
}
static interface IChannel{
public boolean connect();
}
public static void send(IMessage msg, IChannel channel){
if(channel.connect()){
print(msg.getCon());
} else{
print("failed");
}
};
}
class DefaultMessage implements IMessageWarp.IMessage{
public String getCon(){
return "www.mldn.cn";
}
}
class NetChannel implements IMessageWarp.IChannel{
public boolean connect(){
return true;
}
}
main{
IMessageWarp.send(new DefaultMessage(), new NetChannel());
}
之所以使用static定义的内部接口,主要是因为这些操作是属于一组相关的定义,有了外部接口之后可以更加清楚的描述接口的主要功能。
方法中定义内部类
内部类可以再任一结构中进行定义,在方法中定义内部类形式较多。
class Outer{
private String msg = "www.mldn.cn";
public void fun(long time){
class Inner{
//内部类
public void print(){
print(Outer.this.msg);
print(time);
}
}
new Inner().print(); //方法中直接实例化内部类对象
}
}
main{
new Outer().fun(2334234L);
}
此时fun()方法内部有Inner定义,内部类可以直接访问外部类中的私有属性,也可以访问方法中的参数,而对于方法中的参数直接访问是从JDK1.8开始支持的。
匿名内部类
匿名内部类是简化的内部类的处理形式,主要是在抽象类和接口的子类上使用。
interface IMessage{
public void send(String str);
}
class MessageImpl implements IMessage{
public void send(String str){
print(str);
}
}
main{
IMessage msg = new MessageImpl();
msg.send("test");
}
若IMessage中MessageImpl子类只使用一次,就没必要将其定义为单独的类。此时可以利用匿名内部类解决问题。
interface IMessage{
public void send(String str);
}
main{
IMessage msg = new IMessage(){
//匿名内部类
public void send(String str){
print(str);
}
};
msg.send("test");
}
有时为了方便体现出匿名内部类使用,可以利用静态方法做一个内部的匿名内部类实现。
interface IMessage{
public void send(String str);
public static IMessage getInstance(){
return new IMessage(){
public void send(String str){
print(str);
}
}
}
}
main{
IMessage.getInstance().send("test");
}
匿名内部类是一个没有名字的只能使用一次的并且结果固定的子类操作。