Java 内部类

本文详细阐述了内部类如何访问外部类的私有属性,展示了静态内部类、匿名内部类和方法中定义内部类的应用,以及它们在技术场景中的优势。重点介绍了私有内部类的使用和接口内部类的实例化方式。

内部类基本定义

class Outer {
	private String msg = "www.mldn.cn" ;	// 私有成员属性
	public void fun(){	//普通方法
		Inner in = new Inner() ;	// 实例化内部类对象
		in.print() ;
	}
	class Inner {	// 在Outer类的内部定义了Inner类
		public void print(){
			System.out.println(Outer.this.msg) ;	// Outer类中的属性
		}
	}
}
public class StringDemo {
	public static void main(String args[]){ 
		Outer out = new Outer();	//实例化外部类对象
		out.fun() ;	// 调用外部类中的方法
	}
}

如定义在外部

class Outer {
	private String msg = "www.mldn.cn" ;	// 私有成员属性
	public void fun(){	//普通方法
		// 思考五:需要将当前对象Outer传递到Inner类之中
		Inner in = new Inner(this) ;// 实例化内部类对象
		in.print() ;
	}
	// 思考一:msg属性如果要被外部访问需要提供有getter方法
	public String getMsg(){
		return this.msg ;
	}
}
class Inner {	// 在Outer类的内部定义了Inner类
		// 思考三:Inner这个类对象实例化的时候需要Outer类的引用 
		private Outer out ;
		// 思考四:应该通过Inner类的构造方法获取Outer类对象
		public Inner(Outer out){
			this.out = out ;
		}
		public void print(){
			// 思考二:如果要想调用外部类的getter方法,那么一定需要由Outer类对象
			System.out.println(this.out.getMsg()) ;	// Outer类中的属性
		}
	}
public class StringDemo {
	public static void main(String args[]){ 
		Outer out = new Outer();	//实例化外部类对象
		out.fun() ;	// 调用外部类中的方法
	}
}

以发现,整体的操作之中,折腾了半天主要目的就是为了让Inner这个内部可以访问Outer这个类中的私有属性,但是如果不用内部类的时候整体代码非常麻烦,所以得出内部类的优点:轻松的访问外部类中的私有属性。

内部类相关说明
内部类可以方便的访问外部类私有成员或私有方法,同理,外部类也可以轻松的访问内部类中的私有成员或私有方法。

package com.msc.high;

class Outer {
    private String msg = "外部类成员属性" ;	// 私有成员属性
    public void fun(){	//普通方法
        Inner in = new Inner( ) ;// 实例化内部类对象
        in.print() ;
        System.out.println(in.info) ;	// 访问内部类的私有属性
    }
    public void print(){
        System.out.println("外部类方法");
    }
    class Inner {	// 在Outer类的内部定义了Inner类
        private String info = "内部类成员属性" ;
        public void print(){
            System.out.println(Outer.this.msg) ;	// Outer类中的属性
            Outer.this.print();
        }
    }
}
public class InnerDemo {
    public static void main(String[] args) {
        Outer out = new Outer();	//实例化外部类对象
        out.fun() ;	// 调用外部类中的方法
    }
}

在这里插入图片描述
但是需要注意的是,内部类本身也属于一个类,虽然在大部分的情况下内部类往往是被外部类包裹的,但是外部依然可以产生内部类的实例化对象,而此时内部类实例化对象的格式如下:

外部类.内部类 内部类对象 = new 外部类().new 内部类() ;

在内部类编译完成之后会自定形成一个“ Outer I n n e r . c l a s s ” 类 文 件 , 其 中 “ Inner.class ”类文件,其中“ Inner.class”类文件,其中“”这个符号换到程序之中就变为了“ . ”所以内部类的全称:“外部类.内部类”。内部类与外部类之间可以直接进行私有成员的访问,这样一来内部类如果要是提供有实例化对象了,一定要先保证外部类已经实例化了,

class Outer {
	private String msg = "www.mldn.cn" ;	// 私有成员属性
	class Inner {	// 在Outer类的内部定义了Inner类
		private String info = "今天天气不好,收衣服啦!" ;
		public void print(){
			System.out.println(Outer.this.msg) ;	// Outer类中的属性
		}
	}
}

public class StringDemo {
	public static void main(String args[]){ 
		Outer.Inner in = new Outer().new Inner() ;
		in.print() ;
	}
}

如果此时Inner类只允许Outer类来使用,那么再这样的情况下就可以使用private进行私有定义。

class Outer {
	private String msg = "www.mldn.cn" ;	// 私有成员属性
	private class Inner {	// 在Outer类的内部定义了Inner类
		private String info = "今天天气不好,收衣服啦!" ;
		public void print(){
			System.out.println(Outer.this.msg) ;	// Outer类中的属性
		}
	}
}

public class StringDemo {
	public static void main(String args[]){ 
		Outer.Inner in = new Outer().new Inner() ;
		in.print() ;
	}
}

此时的Inner类无法在外部进行使用。

在Java之中类作为最为基础的结构体实际上还有与之类似的抽象类或者是接口,抽象类与接口中都可以定义内部结构。

interface IChannel {	// 定义接口
	public void send(IMessage msg) ;	// 发送消息
	interface IMessage {	// 内部接口
		public String getContent() ;	// 获取消息内容
	}
}
class ChannelImpl implements IChannel {
	public void send(IMessage msg){
		System.out.println("发送消息:" + msg.getContent()) ;
	}
	class MessageImpl implements IMessage {
		public String getContent(){
			return "www.mldn.cn" ;
		}
	}
}
public class StringDemo {
	public static void main(String args[]){ 
		IChannel channel = new ChannelImpl() ;
		channel.send(((ChannelImpl)channel). new MessageImpl()) ;
	}
}

内部抽象类可以定义在普通类、抽象类、接口内部都是可以的。

interface IChannel {	// 定义接口
	public void send() ;	// 发送消息
	abstract class AbstractMessage {
		public abstract String getContent() ;
	}
}
class ChannelImpl implements IChannel {
	public void send(){
		AbstractMessage msg = new MessageImpl() ;
		System.out.println(msg.getContent()) ;
	}
	class MessageImpl extends AbstractMessage {
		public String getContent(){
			return "www.mldn.cn" ;
		}
	}
}
public class StringDemo {
	public static void main(String args[]){ 
		IChannel channel = new ChannelImpl() ;
		channel.send() ;
	}
}

如果现在定义了一个接口,那么可以在内部利用类实现该接口,在JDK1.8之后追加了static方法可以不受到实例化对象的控制,现在就可以利用此特性来完成功能。
interface IChannel {	// 定义接口
	public void send() ;	// 发送消息
	class ChannelImpl implements IChannel {
		public void send(){
			System.out.println("www.mldn.cn") ;
		}
	}
	public static IChannel getInstance(){
		return new ChannelImpl() ;
	}
}
public class StringDemo {
	public static void main(String args[]){ 
		IChannel channel = IChannel.getInstance() ;
		channel.send() ;
	}
}

内部类是一种非常灵活的定义结构,只要语法符合要求,各种需求都可以实现。
static定义内部类
如果说现在在内部类使用了static定义,那么这个内部类就变为了“外部类”,static定义的都是独立于类的外部结构,所以该类结构就相当于是一个独立的程序类。需要注意的是,static定义的不管是类还是方法只能够访问static成员,所有static定义的内部类只能够访问外部的static方法或成员属性。

package com.msc.high;

class Outer {
    private static String msg = "外部类成员属性" ;	// 私有成员属性
    public  void fun(){	//普通方法
        Inner in = new Inner( ) ;// 实例化内部类对象
        in.print() ;
        System.out.println(in.info) ;	// 访问内部类的私有属性
    }
    public static void print(){
        System.out.println("外部类方法");
    }
    static class Inner {	// 在Outer类的内部定义了Inner类
        private String info = "内部类成员属性" ;
        public void print(){
            System.out.println(Outer.msg) ;	// Outer类中的属性
            Outer.print();
        }
    }
}
public class InnerDemo {
    public static void main(String[] args) {
        Outer out = new Outer();	//实例化外部类对象
        out.fun();
    }
}

class Outer {
	private static final String MSG = "www.mldn.cn" ;
	static class Inner {
		public void print(){
			System.out.println(Outer.MSG) ;
		}
	}
}
public class StringDemo {
	public static void main(String args[]){ 
		Outer.Inner in = new Outer.Inner() ;
		in.print() ;
	}
}

如果以static定义内部类的形式来讲并不常用,static定义内部接口的形式最为常用。


```java
interface IMessageWarp {	// 消息包装
	static interface IMessage {
		public String getContent() ;
	}
	static interface IChannel {
		public boolean connect() ;	// 消息的发送通道
	}
	public static void send(IMessage msg, IChannel channel){
		if(channel.connect()){
			System.out.println(msg.getContent()) ;
		}else {
			System.out.println("消息通道无法建立,消息发送失败!") ;
		}
	} ;	// 消息发送
}
class DefaultMessage implements IMessageWarp.IMessage {
	public String getContent(){
		return "www.mldn.cn" ;
	}
}
class NetChannel implements IMessageWarp.IChannel {
	public boolean connect(){
		return true ;
	}
}
public class StringDemo {
	public static void main(String args[]){ 
		IMessageWarp.send(new DefaultMessage(), new NetChannel()) ;
	}
}

之所以使用static定义的内部接口,主要是因为这些操作是属于一组相关的定义,有了外部接口之后可以更加明确的描述出这些借口的主要功能。
方法中定义内部类
内部类可以在任意的结构中进行定义,这就包括了:类中、方法中、代码块中,但是从实际的开发来讲在方法中定义内部中形式较多。
范例:观察在方法中定义的内部类

```java
class Outer {
	private String msg = "www.mldn.cn" ;
	public void fun(long time){
		class Inner {	// 内部类
			public void print(){
				System.out.println(Outer.this.msg) ;
				System.out.println(time) ;
			}
		}
		new Inner().print() ;	// 方法中直接实例化内部类对象
	}
}
public class StringDemo {
	public static void main(String args[]){ 
		new Outer().fun(23151515) ;
	}
}

此时在fun()方法内部提供有Inner内部类的定义,并且可以发现内部类可以直接访问外部类中的私有属性也可以直接访问方法中的参数,但是对于方法中的参数直接访问是从JDK1.8开始支持的,而在JDK1.8之前,如果方法中定义的内部要想访问方法中的参数则参数前必须追加final。
匿名内部类
匿名内部类是一种简化的内部类的处理形式,其主要是在抽象类和接口的子类上使用的。
与内部类相比匿名内部类只是一个没有名字的只能够使用一次的,并且结构固定的一个子类。

package com.msc.high;

class Outer {
    private static String msg = "外部类成员属性" ;	// 私有成员属性
    public  void fun(){	//普通方法
        Inner in = new Inner( ) ;// 实例化内部类对象
        in.print() ;
        System.out.println(in.info) ;	// 访问内部类的私有属性
    }
    public static void print(){
        System.out.println("外部类方法");
    }
    static class Inner {	// 在Outer类的内部定义了Inner类
        private String info = "内部类成员属性" ;
        public void print(){
            System.out.println(Outer.msg) ;	// Outer类中的属性
            Outer.print();
        }
    }
}
interface IMessage {
    public void send(String str) ;
}
interface IMath {
    public int add(int x, int y) ;
}
class MessageImpl implements IMessage {
    public void send(String str){
        System.out.println(str) ;
    }
}
interface IMessageb {
    public void send(String str) ;
    public static IMessage getInstance(){
        return new IMessage(){
            public void send(String str){
                System.out.println(str) ;
            }
        };
    }
}
public class InnerDemo {
    public static void main(String[] args) {
        IMessage msga = new MessageImpl() ;
        msga.send("匿名内部类1") ;

        IMessage msgb = new IMessage(){
            public void send(String str){
                System.out.println(str) ;
            }
        };
        msgb.send("匿名内部类2") ;
        IMessageb.getInstance().send("匿名内部类3") ;
        IMessage msgd = (str)->{
            System.out.println("Lambda表达式:"+str);
        };
        msgd.send("匿名内部类4");
        IMath math = (t1,t2)->{
            return t1+t2 ;
        };
        System.out.println("Lambda表达式匿名内部类5:"+math.add(10,20));
        IMath mathb = (t1,t2)->t1+t2 ;
        System.out.println("Lambda表达式匿名内部类6:"+mathb.add(20,20));
    }
}

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

隔壁de小刘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值