Java读书笔记十五(Java中的内部类)

前言

Java从JDK1.1的时候,就开始引入内部类的概念了,那么小编也通过这篇博客来分享一下Java中有关内部类的一些特性。

什么是内部类?

在很多情况下,类被定义成一个独立的程序单元,但是有时候也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就称为内部类。

从语法上来看的话,定义内部类和定义外部类的语法大致相同,内部类除了需要定义在其他类里面之外,还存在如下两点区别。

1.内部类比外部类多使用三个修饰符:private——protected、static——外部类不可以使用这三个修饰符。

2.非静态内部类不能拥有静态成员。

除了以上两点之外,其他的地方都与普通的类相同,下面来列举一下常见的内部类操作。

非静态内部类

定义内部类也非常简单,只要把一个类放在另一个类内部定义即可,甚至都可以放置在方法的内部。

package com.test;
public class Cow
{
	private double weight;
	// 外部类的两个重载的构造器
	public Cow(){}
	public Cow(double weight)
	{
		this.weight = weight;
	}
	// 定义一个非静态内部类
	private class CowLeg
	{
		// 非静态内部类的两个实例变量
		private double length;
		private String color;
		// 非静态内部类的两个重载的构造器
		public CowLeg(){}
		public CowLeg(double length , String color)
		{
			this.length = length;
			this.color = color;
		}
		// 下面省略length、color的setter和getter方法
		public void setLength(double length)
		{
			this.length = length;
		}
		public double getLength()
		{
			return this.length;
		}
		public void setColor(String color)
		{
			this.color = color;
		}
		public String getColor()
		{
			return this.color;
		}
		// 非静态内部类的实例方法
		public void info()
		{
			System.out.println("当前牛腿颜色是:"
				+ color + ", 高:" + length);
			// 直接访问外部类的private修饰的成员变量
			System.out.println("本牛腿所在奶牛重:" + weight);   //①
		}
	}
	public void test()
	{
		CowLeg cl = new CowLeg(1.12 , "黑白相间");
		cl.info();
	}
	public static void main(String[] args)
	{
		Cow cow = new Cow(378.9);
		cow.test();
	}
}

在上述中非静态内部类的成员可以访问外部类的private成员,但反过来就不成立了。非静态内部类的成员只在非静态内部类范围内是可知的,并不能被外部类直接使用。如果外部类需要访问非静态内部类的成员,则必须显式创建非静态内部类对象来调用访问其实例成员。

package com.test;
public class Outer
{
	private int outProp = 9;
	class Inner
	{
		private int inProp = 5;
		public void acessOuterProp()
		{
			// 非静态内部类可以直接访问外部类的private成员变量
			System.out.println("外部类的outProp值:"
				+ outProp);
		}
	}
	public void accessInnerProp()
	{
		// 外部类不能直接访问非静态内部类的实例变量,
		// 下面代码出现编译错误
		// System.out.println("内部类的inProp值:" + inProp);
		// 如需访问内部类的实例变量,必须显式创建内部类对象
		System.out.println("内部类的inProp值:"
			+ new Inner().inProp);
	}
	public static void main(String[] args)
	{
		// 执行下面代码,只创建了外部类对象,还未创建内部类对象
		Outer out = new Outer();      //①
		out.accessInnerProp();
	}
}

注意:非静态内部类中不能有静态方法、静态成员变量、静态初始化块。

静态内部类

如果使用static来修饰一个内部类,则这个内部类就属于外部类本身,而不属于外部类的某个对象,因此使用static修饰的内部类被称为类内部类,有的地方也称为静态内部类。静态内部类可以包含静态成员,也可以包含非静态成员。根据静态成员不能访问非静态成员的规则,静态内部类不能访问外部类的实例成员,只能访问外部类的类成员。

package com.test;
public class StaticInnerClassTest
{
	private int prop1 = 5;
	private static int prop2 = 9;
	static class StaticInnerClass
	{
		// 静态内部类里可以包含静态成员
		private static int age;
		public void accessOuterProp()
		{
			// 下面代码出现错误:
			// 静态内部类无法访问外部类的实例变量
			System.out.println(prop1);
			// 下面代码正常
			System.out.println(prop2);
		}
	}
}

匿名内部类

使用匿名内部类可以创建那种只需要一次使用的类,并且创建匿名内部类时会立即创建一个该类的实例,但是也需要注意一下规则

1.匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象,因此不允许将匿名内部类定义成为抽象类

2.匿名内部类不能定义构造器,由于匿名内部类没有类名,所以无法定义构造器

package com.test;
interface Product
{
	public double getPrice();
	public String getName();
}
public class AnonymousTest
{
	public void test(Product p)
	{
		System.out.println("购买了一个" + p.getName()
			+ ",花掉了" + p.getPrice());
	}
	public static void main(String[] args)
	{
		AnonymousTest ta = new AnonymousTest();
		// 调用test()方法时,需要传入一个Product参数,
		// 此处传入其匿名实现类的实例
		ta.test(new Product()
		{
			public double getPrice()
			{
				return 567.8;
			}
			public String getName()
			{
				return "AGP显卡";
			}
		});
	}
}

时间: 2024-10-13 21:36:30

Java读书笔记十五(Java中的内部类)的相关文章

Java进阶(三十五)java int与integer的区别

Java进阶(三十五)java int与integer的区别 前言 int与integer的区别从大的方面来说就是基本数据类型与其包装类的区别: int 是基本类型,直接存数值,而integer是对象,用一个引用指向这个对象. 1.Java 中的数据类型分为基本数据类型和复杂数据类型 int 是前者而integer 是后者(也就是一个类):因此在类进行初始化时int类的变量初始为0.而Integer的变量则初始化为null. 2.初始化时: int i =1; Integer i= new In

Java进阶(二十五)Java连接mysql数据库(底层实现)

Java进阶(二十五)Java连接mysql数据库(底层实现) 前言 很长时间没有系统的使用java做项目了.现在需要使用java完成一个实验,其中涉及到java连接数据库.让自己来写,记忆中已无从搜索.特将之前使用的方法做一简单的总结.也能够在底层理解一下连接数据库的具体步骤. 实现 首先需要导入相关的jar包,我使用的为:mysql-connector-java-5.1.7-bin.jar. 下面来看一下我所使用的数据库连接方法类: MysqlUtil.java package cn.edu

Java读书笔记十二(Java中的代码块)

前言 我们知道在java中通过构造器来为对象进行初始化操作,但是在java中与构造器类似的还有初始化块的操作,下面小编来为大家分享一下. 初始化块使用 在Java中初始化块是java中出现的第4中成员,前三种分别是成员变量.方法和构造器.一个类中可以有多个初始化块,并且相同类型的初始化块是按照顺序依次执行的.初始化块的修饰符只能是static,初始化块可以包含任何可执行语句,包括定义局部变量.调用其他对象方法,以及使用分支.循环语句等 /** * @FileName: test.java * @

Java读书笔记十四(java中的抽象类)

前言 在java中,有时候需要对类的行为进行提取,因此也就有了抽象类和接口的概念,这篇博客,小编来剖一下java中的抽象类和接口.  抽象方法和抽象类 抽象方法和抽象类的规则如下: 1.抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽线方法不能有方法体 2.抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例.即使抽象类里不可包含抽象方法,这个抽象类也不能被创建实例. 3.抽象类可以包含成员变量.方法(普通方法和抽象方法都可以

Java读书笔记十一(Java中的内省机制)

1.前言 最近在学习Java的时候,突然发现了这个概念,鉴于好奇心的压迫,于是打算写一篇博客来总结一下. 2.什么是内省机制 为了让程序员们更好的从左Java对象的属性,SUN公司开发了一套API,就被我们称为"内省",有利于我们对类对象的属性的操作,减少了代码的数量. 3.内省和反射有什么区别 反射式在运行状态把Java类中的各种成分映射成相应的Java类,可以动态的获取所有的属性以及动态调用任意一个方法,强调的是运行状态. 内省机制是通过反射来实现的,BeanInfo用来暴露一个b

Think in java读书笔记之:java匿名内部类的继承和覆盖

内部类的继承 Java中继承匿名内部类一个要结局的问题就是,内部类的构造器必须要指向其外围对象的引用,所以要采取特殊的语法.书上给的示例代码的可有编译版本,必须在继承的内部类的构造器内添加enclosingClassReference.super(). 1 class WithInner{ 2 class Inner{} 3 } 4 public class InheritInner extends WithInner.Inner{ 5 InheritInner(){ 6 enclosingCl

How tomcat works 读书笔记十五 Digester库

Digester库 在前面的几个章节里,我们对tomcat里各个组件的配置完全是使用写硬编码的形式完成的. 如 Context context = new StandardContext(); Loader loader = new WebappLoader(); context.setLoader(loader); 就完成了向context容器里添加WepappLoader的功能. 这么做的问题就在于,一旦我想更改配置就必须得重新加载Bootstrap类. 幸运的是tomcat的设计者使用了一

How tomcat works 读书笔记十五 Digester库 下

在这一节里我们说说ContextConfig这个类. 这个类在很早的时候我们就已经使用了(之前那个叫SimpleContextConfig),但是在之前它干的事情都很简单,就是吧context里的configured变量置为true.在这里我们看看完整版的ContextConfig都干了什么. 在tomcat的实际部署中,StandContext类的实际监听器是org.apache.catalina.startup.ContextConfig的实例. ContextConfig完成加载验证器阀,

《Java编程那点事儿》读书笔记(五)

System 1)arraycopy int[] a = {1.2.3.4}; int[] b = new int[5]; System.arraycopy(a,1,b,3,2); //把数组a中从下标1开始的元素复制到数组b中下标为3的位置,总共复制2个元素 2)currentTimeMillis long l = System.currentTimeMillis(); //返回当前时间与1970年01月01日0时0分0秒的差值数(毫秒) 3)gc:请求系统进行垃圾回收 4)public st