内部类是一种常见的嵌套结构,利用这样的结构使得内部类可以与外部类共存,并且方便地进行私有操作的访问。
内部类基本概念
内部类(内部定义普通类、抽象类、接口的统称)是指一种嵌套的结构关系,即在一个类的内部除了属性和方法外还可以继续定义一个类结构,这样就使得程序的结构定义更加灵活。
package cn.uihtml.demo;
class Outer{
private String msg = 'www.uihtml.cn';
public void fun() {
Inner in = new Inner();
in.print();
// 访问内部类的私有属性
System.out.println(in.info);
}
class Inner {
private String info = '内部类私有属性';
public void print() {
System.out.println(Outer.this.msg);
}
}
}
package cn.uihtml.demo;
class JavaDemo {
public static void main(String[] args) {
Outer out = new Outer();
out.fun();
}
}
在内部类的结构中,不仅内部类可以方便地访问外部类的私有成员,外部类也同样可以访问内部类的私有成员。内部类本身是一个独立的结构,这样在进行普通成员属性访问时,为了明确地标记处属性是外部类所提供,可以采用【“外部类.this.属性”】的形式进行标注。
需要注意的是,内部类虽然被外部类所包裹,但是其本身也属于一个完整类,所以也可以直接进行内部类对象的实例化,此时可以采用以下的语法格式。
外部类.内部类 内部类对象 = new 外部类().内部类();
在此语法格式中,要求必须先获取相应的外部类实例化对象后,才可以利用外部类的实例化对象进行内部类对象实例化操作。
内部类不仅可以在类中定义,也可以应用在接口和抽象类中,即可以定义内部的接口或内部抽象类。
package cn.uihtml.demo;
interface IChannel {
public void send(IMessage msg);
interface IMessage{
public String getContent();
}
}
package cn.html.demo;
class ChannelImpl implements IChannel {
@Override
public void send(IMessage msg) {
System.out.println('发送消息:' + msg.getContent());
}
class MessageImpl implements IMessage {
@Override
public String getContent() {
return 'www.uihtml.cn'
}
}
}
package cn.uihtml.demo;
class JavaDemo {
public static void main(String[] args) {
IChannel channel = new ChannelImpl();
channel.send(((ChannelImpl) channel).new MessageImpl())
}
}
static定义内部类
在进行内部类定义的时候,也可以通过static关键字来定义,此时的内部类不再受外部类实例化对象的影响,所以等同于是一个“外部类”,内部类的名称为“外部类.内部类”。使用static定义的内部类只能够调用外部类中static定义的结构,并且在进行内部类实例化的时候也不再需要先获取外部类实例化对象,static内部类对象实例化格式如下。
外部类.内部类 内部类对象 = new 外部类.内部类();
package cn.uihtml.demo;
class Outer {
private static final String MSG = 'www.uihtml.cn';
static class Inner {
public void print() {
System.out.println(Outer.MSG);
}
}
}
package cn.uihtml.demo;
class JavaDemo {
public static void main(String[] args) {
Outer.Inner in = new Outer.Inner();
in.print();
}
}
匿名内部类
在一个接口或抽象类定义完成后,在使用前都需要定义专门的子类,随后利用子类对象的向上转型才可以使用接口或抽象类。但是在很多时候某些子类可能只是用一次,那么单独为其创建一个类文件就会非常浪费,此时就可以利用匿名内部类的概念来解决此类问题。
package cn.uihtml.demo;
interface IMessage {
public void send(String str);
}
package cn.uihtml.demo;
class JavaDemo {
public static void main(String[] args) {
IMessage msg = new IMessage() {
public void send(String str) {
System.out.println(str);
}
};
msg.send('www.uihtml.cn');
}
}
Lambba表达式
Lambba表达式是JDK1.8中引入的重要技术特征。所谓的Lambba表达式,是指应用在SAM(Single Abstract Method,含有一个抽象方法的接口)环境下的一种简化定义形式,用于解决匿名内部类的定义复杂问题,在Java中Lambba表达式的基本语法形式如下。
// 定义方法体
(参数1,参数2,…)->{方法体}
// 直接返回结果
(参数1,参数2,…)-> 语句
在给定的格式中,参数与要覆写的抽象方法的参数对应,抽象方法的具体操作就通过方法体来进行定义。
package cn.uihtml.demo;
interface IMessage {
public void send(String str);
}
package cn.uihtml.demo;
class JavaDemo {
public static void main(String[] args) {
IMessage msg = (str) -> {
System.out.println('发送消息:' + str);
}
msg.send('www.uihtml.cn');
}
}
在进行Lambba表达式定义的过程中,如果要实现的方法体只有一行,则可以省略“{}”。
在Lambba表达式中已经明确要求Lambba是应用在接口上的一种操作,并且接口中只允许定义一个抽象方法。但是在一个项目开发中往往会定义大量的接口,而为了分辨出Lambba表达式的使用接口,可以在接口上使用@FunctionInterface注解声明,这样表示此为函数式接口,里面只允许定义一个抽象方法。
package cn.uihtml.demo;
@FunctionInterface
interface IMessage {
public void send(String str);
}
需要注意的是,在函数式接口中依然可以定义普通方法和静态方法。
方法的引用
在Java中利用对象的引用传递可以实现不同的对象名称操作同一块堆内存空间的操作,而从JDK1.8开始,方法也支持引用操作,这样就相当于为方法定义了别名。方法引用的形式一共有有以下4种。
// 引用静态方法
类名称::static 方法名称
// 引用某个对象的方法
实例化对象:: 普通方法
// 引用特定类型的方法
特定类:: 普通方法
// 引用构造方法
类名称:: new
链表
在项目开发种数组是一个重要的逻辑组成。传统数组中最大的缺陷在于其一旦声明则长度固定,不便于程序开发,而要想要解决这一缺陷,就可以利用链表数据结构实现。
链表(动态数组)的本质是利用对象引用的逻辑关系来实现类似数组的数据存储逻辑,一个链上由若干个节点(node)所组成,每一个节点依靠对上一个节点的引用形成一个“链”的形式。
数组本身是需要进行多个数据的信息保存,但是数据本身并不能够描述出彼此间的先后顺序,所以就需要将数据包装在节点(node)中,每一个节点除了要保存数据信息外,一定还要保存有下一个节点(node)的引用,而在链表中会保存一系列的节点对象。
在进行Node类设计时,为了避免程序开发中可能出现的ClassCastException安全隐患,对于保存的数据类型都用泛型进行定义,这样就可以保证在一个链表中的数据类型统一。
package cn.uihtml.demo;
class Node {
private E data;
private Node next;
public Node(E data) {
this.data = data;
}
public E getData() {
return this.data;
}
public void setNext(Node next) {
this.next = next;
}
public Node getNext() {
return this.next;
}
}
package cn.uihtml.demo;
class LinkDemo {
public static void main(String[] args) {
Node n1 = new Node('火车头');
Node n2 = new Node('车厢一');
node n3 = new Node('车厢二');
node n4 = new Node('车厢三');
node n5 = new Node('车厢四');
node n6 = new Node('车厢五');
printNode(n1);
}
public static void printNode(Node node) {
if (node != null) {
System.out.print(node.getData() + '、');
printNode(node.getNext());
}
}
}
原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/java/java-inner-class.html