java中内部类的讲解
java中有一个内部类的概念,由于之前一直比较忙,没有单独拿出时间总结一下,今天我就把内部类的相关知识进行一下汇总,如果有不足之处,欢迎批评指正。
1)java内部类的概念。
在一个类的的内部定义的类被称为java的内部类。内部类提供了更好的封装。而且它可以直接访问外部类的private成员。
2)内部类的分类
根据内部类的位置不同,可以大致分为一下两类:
1.普通内部类又叫成员内部类,在方法体的外面定义的内部类
其中普通内部类又分为静态(static修饰的内部类)和非静态(非static修饰的内部类)
2.局部内部类又叫方法内部类,在方法体中定义的内部类
其中局部内部类又分为静态(static方法中的内部类)和非静态(非static方法中的内部类)以及匿名内部类。
3)每种内部类的详细详解
1.普通非静态内部类
package com.yonyou.test;
public class Test {
public static void main(String[] args) {
//调用相应的内部类,下面是在调用内部类的常用方法
GeneralInnerClass gic=new GeneralInnerClass();
GeneralInnerClass.Car car=gic.new Car();
car.run();
//下面是调用内部类的简便方法
// new GeneralInnerClass().new Car().run();
//调用private修饰的内部类Car2
Speed car2=gic.getCar2();//实现了很好的隐藏
car2.run(); //你甚至连这两个内部类的名字都没有看见!隐藏你不想让别人知道的操作,也即封装性。
}
}
/**
* 定义普通内部类
* @author lenovo
*
*/
class GeneralInnerClass{
String carName="奥迪A8L";
protected class Car{ //内部类的修饰符可以是private,protected,public或者省略,
public void run(){ //可以将相应的内部类理解为相应的类成员即可
System.out.println("小汽车的名字为:"+getCarName()); //内部类调用外部类的方法
System.out.println("小汽车\""+carName+"\"跑的很快哦~~"); //内部类调用外部类的属性
}
}
/**
* 创建一个使用private修饰的内部类Car2
* @author lenovo
*
*/
private class Car2 implements Speed{
@Override
public void run(){
System.out.println("大家好,我是第二辆小汽车Car2哦~");
}
}
//返回private修饰的内部类对象Car2
public Car2 getCar2(){
return new Car2();
}
public String getCarName(){
return carName;
}
}
/**
* 创建一个接口,用于测试private修饰的Car2,Car2类实现了这个接口
* 利用接口回调
* @author lenovo
*
*/
interface Speed{
void run();
}
对于这种普通内部类除了上面标注外,需要注意一下几点:
1.普通内部类中不能有静态成员变量和静态成员方法
2.想要引用内部类,必须创建外部类的引用,即内部类不能离开外部类而独立存在
3.可以内部类理解为外部类的一个成员,一个内部类对象可以访问创建它的外部类对象的内容,需要注意的是内部类里的一个成员变量与外部类
的一个成员变量同名,也即外部类的同名成员变量被屏蔽,那么如果需要访问外部类的成员变量可以通过:外部类名.this.变量名
例如:InnerClass.this.carName
4.所有的内部类都需要注意其构造方法,所有的内部类都没有无参的构造器,系统都会为其增加一个默认的构造参数.
因为所有的内部类都有一个默认的构造参数,其值为外部类对象,这样也就更好的理解了对于外部类
而言,内部类仅仅是他的一个成员而已,即内部类不能够离开外部类而独立存在哦...
为了更好的理解请看下面的例子:
package com.yonyou.test; /**
* 测试类
* @author 小浩
* @创建日期 2015-3-20
*/ public class Test
{
public static void main(String[] args) throws InstantiationException, IllegalAccessException{
//创建内部类的实例
System.out.println(new Outter().new Inner().getStr());
//通过反射的方法创建内部类的实例
System.out.println(Outter.Inner.class.newInstance());
} } /**
* 创建外部类这个测试对象
* @author 小浩
* @创建日期 2015-3-19
*/
class Outter{
private String str="Hello World";
/**
* 创建内部测试类对象
*/
class Inner{
//访问外部类private属性
public String getStr(){
return str;
}
} }
上面的程序报的错误为:
Hello World
Exception in thread "main" java.lang.InstantiationException: com.yonyou.test.Outter$Inner
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at com.yonyou.test.Test.main(Test.java:1
主要原因就是因为在反射的过程中jdk会通过反射机制使用原来无参的构造方法创建相关的对象,而内部类在创建的过程中,
会默认增加一个外部类的参数,因为没有无参的构造器,所以在反射内部类的时候会出现错误...
2.普通静态内部类
package com.yonyou.test;
public class Test {
public static void main(String[] args) {
//静态内部类的使用方式
GeneralInnerClass.Car car=new GeneralInnerClass.Car();
car.run();
}
}
/**
* 定义普通内部类
* @author lenovo
*
*/
class GeneralInnerClass{
static String carName="奥迪A8L";
static class Car{ //内部类的修饰符可以是private,protected,public或者省略,
static String value="汽车静态内部类";
public void run(){ //可以将相应的内部类理解为相应的类成员即可
System.out.println("小汽车的名字为:"+getCarName()); //内部类调用外部类的方法,外部类方法必须是static的
System.out.println("小汽车\""+carName+"\"跑的很快哦~~"); //内部类调用外部类的属性,外部类的属性必须是static的
}
}
public static String getCarName(){
System.out.println(Car.value);
return carName;
}
}
对于这种静态内部类除了上面标注的外,需要注意以下几点:
1.普通静态和非静态类的区别就在于静态内部类没有了指向外部的引用
2.普通静态内部类如果想要使用外部类中的成员(包括属性和方法),那么要求对应的成员是static的
3.静态内部类是属于相应的外部类的静态成员
3.局部非静态方法中的内部类
package com.yonyou.test;
public class Test {
public static void main(String[] args) {
//局部非静态内部类的使用方式
MethodInnerClass car=new MethodInnerClass();
car.method();
}
}
/**
* 定义局部内部类
* @author lenovo
*
*/
class MethodInnerClass{
String carName2="奥迪A6L";
public void method(){
final String carName="奥迪A8L";//局部变量必须是final的,否则无法访问到
class Car{ //局部内部类除了final或者abstract外里面不能有任何修饰符
public void run(){
System.out.println("访问方法中的变量:小汽车\""+carName+"\"跑的很快哦~~"); //方法内部类调用方法中的局部变量,对应的局部变量必须是final修饰的
System.out.println("访问外部类的方法:小汽车的名字为:"+getCarName2()); //方法内部类调用外部类的方法
System.out.println("访问外部类的变量:小汽车\""+carName2+"\"跑的很快哦~~"); //方法内部类调用外部类的属性
}
}
//创建非静态内部类并调用非静态内部类的方法
new Car().run();
}
public String getCarName2(){
return carName2;
}
}
定义局部内部类的时候需要主要一下事项:
1.局部内部类除了final或者abstract外里面不能有任何修饰符 ps:对于所有的java类而言,前面的修饰符可以为:public/默认/final/abstract/strictfp,而对于内部类而言其修 饰符较多可以为public/默认/protected/private/final/abstract/strictfp
2.局部非静态内部类同样可以访问外部类的成员(包括属性和方法)
3.局部非静态内部类的创建只能在方法内完成
4.局部静态方法中的内部类
package com.yonyou.test;
public class Test {
public static void main(String[] args) {
MethodInnerClass.method();
}
}
/**
* 定义局部内部类
* @author lenovo
*
*/
class MethodInnerClass{
static String carName2="奥迪A6L";
public static void method(){
final String carName="奥迪A8L";//局部变量必须是final的,否则无法访问到
class Car{ //局部内部类除了final或者abstract外里面不能有任何修饰符
public void run(){
System.out.println("访问方法中的变量:小汽车\""+carName+"\"跑的很快哦~~"); //方法内部类调用方法中的局部变量,对应的局部变量必须是final修饰的
System.out.println("访问外部类的方法:小汽车的名字为:"+getCarName2()); //方法内部类调用外部类的方法
System.out.println("访问外部类的变量:小汽车\""+carName2+"\"跑的很快哦~~"); //方法内部类调用外部类的属性
}
}
//在静态方法中创建内部类并调用相应的方法
new Car().run();
}
public static String getCarName2(){
return carName2;
}
}
需要注意的是:
1.静态方法中的内部类不能用static修饰
2.静态方法中的内部类可以访问方法外的static成员变量
3.静态方法中的内部类如果访问本方法中的局部变量的话,对应的局部变量必须是final修饰的
5.匿名内部类
一方面匿名内部类在使用上更加简洁,另外一方面匿名内部类属于对应的方法,会随着方法的执行完毕而被回收,资源的占用更少。
当你只需要创建一个类的对象而且用不上它的名字时,使用匿名内部类可以使代码看上去简洁清楚。
当一个内部类的类声名只是在创建此类对象时用了一次,而且要产生的新类需继承于一个已有的父类或实现一个接口,才能考虑用匿名类,由
于匿名类本身无名,因此它也就不存在构造方法,它需要显示地调用一个无参的父类的构造方法,并且重写父类的方法。
package com.yonyou.test;
public class Test {
public static void main(String[] args) {
//创建一个接口对应的匿名内部类
new BigCar(){
@Override
public void run() {
System.out.println("您正在调用大卡车的匿名内部类(接口)哦~~");
}
}.run();
//创建一个抽象类的对象实现匿名内部类
new SmallCar(){
@Override
public void run() {
System.out.println("您正在调用小卡车的匿名内部类(抽象类)哦~~");
}
}.run();
//匿名类最长用的一种方式,在多线程中使用相关的内容
//使用Thread类实现多线程的相关内容
new Thread(){
@Override
public void run(){
System.out.println("使用Thread类实现多线程调用的方法");
}
}.start();
//实现Runnable接口实现多线过程的机制
Runnable runnable=new Runnable(){
@Override
public void run() {
System.out.println("使用Runnbale接口的方式实现多线程的相关机制~~");
}
};
Thread thread=new Thread(runnable);
thread.start();
//多线程内部匿名类的终极版
new Thread(
new Runnable(){
public void run(){
System.out.println("实现多线程机制,利用内部类的方法的终极方案");
}
}
).start();
}
}
/**
* 创建一个大卡车的接口
* @author lenovo
*
*/
interface BigCar{
public void run();
}
/**
* 创建一个小卡车的抽象类
*/
abstract class SmallCar{
public abstract void run();
}
在使用匿名列的时候需要注意一下几点:
1.匿名类不能独立存在,必须定义在相应的方法中或者代码块中(自己没有测试)。
2.匿名类内部一般需要重写abstract方法或者是实现相关的接口。
3.匿名内部类中不能存在构造方法哦。
·匿名内部类不能定义任何静态成员、方法和类。
·匿名内部类不能是public,protected,private,static。
·只能创建匿名内部类的一个实例。
·一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
·因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
java中内部类的讲解的更多相关文章
- JAVA中内部类(匿名内部类)访问的局部变量为什么要用final修饰?
本文主要记录:在JAVA中,(局部)内部类访问某个局部变量,为什么这个局部变量一定需要用final 关键字修饰? 首先,什么是局部变量?这里的局部是:在方法里面定义的变量. 因此,内部类能够访问某局部 ...
- java中内部类的积累
放在一个类的内部的类我们就叫内部类. 二. 作用 1.内部类可以很好的实现隐藏 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以 2.内部类拥有外围类的所有元素的访 ...
- Java中内部类的骚操作
10.1 如何定义内部类 如代码10.1-1 所示 public class Parcel1 { public class Contents{ private int value = 0; pu ...
- java中内部类使用小结
内部类是指在一个外部类中再定义一个类,类名不需要和文件名相同 内部类可以是静态的,类的修饰符可以是private,default,protect,public修饰 ,而外部类只能是public 和 d ...
- java中内部类的定义与访问规则
java内部类总结 简单来说,内部类就是在我们所熟悉的类中的里面再定义一个类 为什么需要内部类? 当我们描述事物时,事物之中还有事物,我们就用内部类描述事物 因为内部事物在使用外部事物的内容 我举一个 ...
- Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“
声明:本博客为原创博客.未经同意,不得转载.原文链接为 http://blog.csdn.net/bettarwang/article/details/27012421. ...
- Java中IO流讲解(一)
一.概念 IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的类都在IO包中 流按流向分为两种:输入流,输出流 流按操作类型分为两种: 字节流 : 字节流可以操作 ...
- Java中内部类和静态内部类的区别
内部类和静态内部类 示例 public class OuterClass { private int numPrivate = 1; public int numPublic = 2; public ...
- JAVA中内部类和同文件非内部类的总结
java文件的顶层类(即非其它类的内部类),可见范围只有public和非public(包内可见)2种,不能用private或protected修饰.1个Java文件只能有一个public类,且必须与文 ...
随机推荐
- maven创建web工程Spring配置文件找不到
使用maven创建web工程,将Spring配置文件applicationContext.xml放在src/resource下,用eclipse编译时提示class path resource [ap ...
- 基于“基于dockerhub的jetty镜像的ossfs镜像”部署war包,遇到的文件夹读写权限被限制的问题解决方案
前提: “基于dockerhub的jetty镜像的ossfs镜像” 已经搭建好了. 部署准备: 1.本地打包:war包-->idea工具 mvn 打包. 2.本地sh脚本:compile_vps ...
- Visual Studio中用于ASP.NET Web项目的Web服务器
当您在 Visual Studio 中开发 Web 项目时,需要 Web 服务器才能测试或运行它们. 利用 Visual Studio,您可以使用不同的 Web 服务器进行测试,包括 IIS Expr ...
- Overlay网络与物理网络的关系
编者按:无论是云计算还是SDN都把注意力集中在数据中心网络的建设上,各种解决方案层出不穷,其中以VMware为代表的软件厂商提出Overlay网络方案后,为数据中心网络的发展提出了新的思路.那么Ove ...
- Db2数据库在Linux下的安装和配置
一.DB2数据库的安装和配置: 1.安装完成后,需要增加三个操作系统的组和三个操作系统用户,如下: groupadd -g 999 db2iadm1 #(管理实例的组) groupadd -g 99 ...
- 使用BeanUtils方法拷贝不上问题
最近在项目中,发现BeanUtils.copyProperties方法拷贝bean属性时候,有的时候会失效.最后发现是由于项目中引用了spring和common两个包,都有BeanUtils方法,错误 ...
- python中的list和array的不同之处 2
版权声明:本文为博主非原创文章,未经博主允许可以转载. Python中的list和array的不同之处 python中的list是python的内置数据类型,list中的数据类不必相同的,而a ...
- Membership如何得到当前登录的用户名称
System.Web.Security.Membership Membership.GetUser().UserName可以得到当前登录的用户信息.
- excel中日期设置星期
在设置日期格式中-自定义中-设置填入yyyy-mm-dd [$-804]aaa;@ 即可.
- java学习笔记 --- 多线程(线程安全问题——同步代码块)
1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...