zoukankan      html  css  js  c++  java
  • Java内部类超详细总结(含代码示例)

    什么是内部类

    什么是内部类?
    顾名思义,就是将一个类的定义放在另一个类的内部
    概念很清楚,感觉很简单,其实关键在于这个内部类放置的位置,可以是一个类的作用域范围、一个方法的或是一个代码块的作用域范围。
    所以理解了概念只是第一步,掌握细节才能彻底搞定Java的内部类特性。
    看例子,这是最普通的内部类:

    public class Product1 {
    	class Design{
    		private String name = "P30 pro";
    		public String showName() {
    			return name;
    		}
    	}
    
    	class Content{
    		private int i;
    		Content(int value){
    			i = value;
    		}
    		int value() {return i;}
    	}
    	public void show(int value) {
    		Content c = new Content(value);
    		Design d = new Design();
    		System.out.println(d.showName());
    		System.out.println(c.value());
    	}
    	public static void main(String[] args) {
    		Product1 p = new Product1();
    		p.show(6000);
    	}
    }
    

    说明:
    上面这个示例展示了内部类最基础的用法,就是将一个或多个类的定义放在了外围内的内部。可以看到在show()方法中的使用和普通类一样,没有区别。

    另外,在外围类的非静态方法之外的任意位置,不能通过直接new 内部类的方式创建内部类对象。会报编译错误。
    像这样:
    在这里插入图片描述
    还有这样:
    在这里插入图片描述
    如果想要在外围类非静态方法之外创建内部类对象。怎么办呢?

    正确的姿势是这样子:
    在外围类中增加两个公共方法,返回内部类的引用。

    	public Design design() {
    		return new Design();
    	}
    	public Content content(int value) {
    		return new Content(value);
    	}
    

    然后通过外部类对象调用方法的方式获取内部类对象。

    	public static void main(String[] args) {
    		Product2 p = new Product2();
    		p.show(6000);
    		Product2.Content c1 = p.content(100);
    		Product2.Design d1 = p.design();
    	}
    

    值得注意的是,外部类之外的其他类,也是不能直接访问到该外部类的内部类对象的。
    会报编译错误。这也符合内部类的定义,就是为外围类服务的嘛!

    内部类的特性

    1.可以链接到外部类

    当生成一个内部类对象时,此对象与制造它的外围对象之间就有了一种联系,所以它能访问外围对象的所有成员,而不需要任何特殊的条件。

    下面的例子是《Java编程思想》中的示例
    首先定义一个Selector接口

    public interface Selector {
    	boolean end();
    	Object current();
    	void next();
    }
    

    然后定义一个Sequence类,其中定义有一个private的内部类。

    public class Sequence {
    
    	private Object[] items;
    	private int next = 0;
    	public Sequence(int size) {items = new Object[size];}
    	public void add(Object x) {
    		if(next < items.length) {
    			items[next++] = x;
    		}
    	}
    	private class SequenceSelector implements Selector{
    		private int i = 0;
    		public boolean end() {
    			return i == items.length;
    		}
    		public Object current() {
    			return items[i];
    		}
    		public void next() {
    			if(i < items.length) {i++;}
    		}
    	}
    	public Selector selector() {
    		return new SequenceSelector();
    	}
    	public static void main(String[] args) {
    		Sequence sequence = new Sequence(10);
    		for(int i = 0; i < 10; i++) {
    			sequence.add(Integer.toString(i));
    		}
    		Selector selector = sequence.selector();
    		while(!selector.end()) {
    			System.out.print(selector.current() + " ");
    			selector.next();
    		}
    	}
    }
    

    说明:
    可以看到SequenceSelector是一个内部类,其end()、current()和next()都用到了外围类中private的items字段。

    2.使用.this和.new

    .this的用法
    如果需要生成对外部类对象的引用,可以使用外部类的名字后面紧跟圆点和this。
    如下所示:

    public class DotThis {
    	void name() {System.out.println("name");}
    	public class Inner{
    		public DotThis outer() {
    			return DotThis.this;
    		}
    	}
    	public Inner inner() {return new Inner();}
    	public static void main(String[] args) {
    		DotThis dt = new DotThis();
    		DotThis.Inner inner = dt.inner();
    		inner.outer().name();
    	}
    }
    

    需要注意DotThis.this只是产生了正确的外部类引用。并没有创建外部类对象。

    .new的用法
    可以通过该语法创建内部类对象,不过要注意的是要使用外部类的对象去创建。

    public class DotNew {
    	public class Inner{}
    	public static void main(String[] args) {
    		DotNew dn = new DotNew();
    		DotNew.Inner dnInner = dn.new Inner();
    	}
    }
    

    内部类分类

    1、局部内部类

    定义在一个方法中或是方法中某一作用域内的类。称作局部内部类。

    public class Product3 {
    	public Section section(String inputName) {
    		class ASection implements Section{
    			private String name;
    			private ASection(String name) {
    				this.name = name;
    			}
    			@Override
    			public String hello() {
    				return name + " say hello";
    			}
    		}
    		return new ASection(inputName);
    	}
    	public static void main(String[] args) {
    		Product3 p = new Product3();
    		Section section = p.section("aaaaa");
    		System.out.println(section.hello());
    	}
    }
    

    ASection是一个Section接口的实现,Section接口代码如下:

    public interface Section {
    	String hello();
    }
    

    说明:

    • 该内部类在section()方法中,该方法之外不能访问ASection类;
    • 方法内部类不允许使用访问权限修饰符(public、private、protected);
    • 注意方法返回的是Section 的引用,即有向上转型。

    另外还可以将内部类的定义放在方法中某一语句块中,如if语句块中。

    public class Product4 {
    
    	public String check(boolean flag) {
    		String checkId = null;
    		if(flag) {
    			class DetailCheck{
    				private String id;
    				private DetailCheck(String id) {
    					this.id = id;
    				}
    				String getId() {
    					return id;
    				}
    			}
    			DetailCheck dc = new DetailCheck("1111");
    			checkId = dc.getId();
    		}
    		return checkId;
    	}
    	public static void main(String[] args) {
    		Product4 p = new Product4();
    		System.out.println(p.check(true));
    	}
    }
    

    说明:
    DetailCheck内部类在if语句块中,因此它的作用范围也在if语句块的范围之内。超出该范围是不可用的。比如这样就会编译报错:
    在这里插入图片描述

    2、匿名内部类

    匿名内部类其实是一种特殊的方法内部类(局部内部类)。它特殊在于将内部类的定义和其对象创建结合在了一块。没有通过class关键字显示声明内部类名称,故谓之“匿名”。
    看代码示例:

    public class Product5 {
    	public Section section() {
    		return new Section() {
    			private String name = "hayli";
    			@Override
    			public String hello() {
    				// TODO Auto-generated method stub
    				return name + " haha";
    			}
    		};
    	}
    	public static void main(String[] args) {
    		Product5 p = new Product5();
    		p.section();
    	}
    }
    

    说明:
    此处Section可以是接口,也可是基类。

    3、嵌套类(静态内部类)

    使用static关键字修饰的内部类,叫做静态内部类,也称作嵌套类。
    嵌套类和普通内部类之间最大的区别是:

    • 普通内部类对象隐式地保存了一个引用,指向创建它的外部类对象。而嵌套类创建对象,并不需要外部类对象。
    • 不能从嵌套类的对象中访问非静态的外部类对象。
    • 普通内部类不能有static数据和static字段,也不能包含嵌套类,但是嵌套类可以包含所有这些东西。
    public class Product6 {
    	private static int id = 100;
    	private static class BSection implements Section{
    		private String name = "bbbb";
    		@Override
    		public String hello() {
    			return name + " hello";
    		}
    		// 只能访问外部类的静态数据或字段
    		public int getId() {return id;}
    		
    		// 可以包含静态数据或方法
    		static int x = 200;
    		public static void test1() {}
    		
    		// 可以再嵌套一层
    		static class BInner{
    			private String name;
    			static void test1() {System.out.println("inner ===");}
    		}
    	}
    	public static void main(String[] args) {
    		Section section = new BSection();
    		section.hello();
    	}
    

    总结

    本篇介绍了什么是内部类、内部类最普通定义方法和Java内部类的几种具体类型详解。虽然工作中使用内部类的机会不会,但是了解这些最基础的知识,真的在项目中遇到内部类的写法,也能看懂是怎么回事了。

    扫码关注微信公众号:二营长的笔记。回复“二营长”,可领取Java相关技术资料。
    在这里插入图片描述

  • 相关阅读:
    Windows永久修改pip安装源
    MySQL 超键 候选键 主键 外键是什么
    scrapy中间件
    crawlspider
    scrapy
    MongoDB 命令
    如何反扒
    表前缀sw_时
    自增序号,而且默认变量就是$i,也就是说在你的volist标签之内,可以直接使用$i
    html,if标签使用
  • 原文地址:https://www.cnblogs.com/happyone/p/11306419.html
Copyright © 2011-2022 走看看