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中内部类的讲解的更多相关文章

  1. JAVA中内部类(匿名内部类)访问的局部变量为什么要用final修饰?

    本文主要记录:在JAVA中,(局部)内部类访问某个局部变量,为什么这个局部变量一定需要用final 关键字修饰? 首先,什么是局部变量?这里的局部是:在方法里面定义的变量. 因此,内部类能够访问某局部 ...

  2. java中内部类的积累

    放在一个类的内部的类我们就叫内部类. 二. 作用 1.内部类可以很好的实现隐藏 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以 2.内部类拥有外围类的所有元素的访 ...

  3. Java中内部类的骚操作

      10.1 如何定义内部类 如代码10.1-1 所示 public class Parcel1 { public class Contents{ private int value = 0;​ pu ...

  4. java中内部类使用小结

    内部类是指在一个外部类中再定义一个类,类名不需要和文件名相同 内部类可以是静态的,类的修饰符可以是private,default,protect,public修饰 ,而外部类只能是public 和 d ...

  5. java中内部类的定义与访问规则

    java内部类总结 简单来说,内部类就是在我们所熟悉的类中的里面再定义一个类 为什么需要内部类? 当我们描述事物时,事物之中还有事物,我们就用内部类描述事物 因为内部事物在使用外部事物的内容 我举一个 ...

  6. Java中内部类揭秘(一):外部类与非静态内部类的”相互可见性“

               声明:本博客为原创博客.未经同意,不得转载.原文链接为 http://blog.csdn.net/bettarwang/article/details/27012421.     ...

  7. Java中IO流讲解(一)

    一.概念 IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的类都在IO包中 流按流向分为两种:输入流,输出流 流按操作类型分为两种: 字节流 : 字节流可以操作 ...

  8. Java中内部类和静态内部类的区别

    内部类和静态内部类 示例 public class OuterClass { private int numPrivate = 1; public int numPublic = 2; public ...

  9. JAVA中内部类和同文件非内部类的总结

    java文件的顶层类(即非其它类的内部类),可见范围只有public和非public(包内可见)2种,不能用private或protected修饰.1个Java文件只能有一个public类,且必须与文 ...

随机推荐

  1. maven setting.xml 存放位置导致deply失败,显示没有权限401错误

    settings.xml存在于两个地方: 1.安装的地方:$M2_HOME/conf/settings.xml 2.用户的目录:${user.home}/.m2/settings.xml 我只在mav ...

  2. MySQL/MariaDB数据库备份与恢复之mysqlpump入门操作

    创建测试用表:MariaDB [music]>  create table summary(id int,info char(128));Query OK, 0 rows affected (0 ...

  3. 出现GC overhead limit exceeded 的解决方案

    当我在使用MyEclispe IDE创建Maven项目的时候出现  "An internal error occurred during: “Build Project”. GC overh ...

  4. python机器学习——分词

    使用jieba库进行分词 安装jieba就不说了,自行百度! import jieba 将标题分词,并转为list seg_list = list(jieba.cut(result.get(" ...

  5. js,java,ajax实现跨域访问及其原理

    http://blog.csdn.net/saytime/article/details/51540876 这篇文章对跨域访问做了较为细致得分析,我这里做下简单总结 1.实现跨域访问原理: 浏览器由于 ...

  6. json对象与字符串互转方法

    字符串转json对象: var data = eval( '(' + str + ')' ); json对象转字符串: var jsonStr = JSON.stringify( obj );

  7. this关键字详解

    在java中,编译器会为每个对象分配一个this关键字.在代码中使用关键字可以使代码更优雅.下面我就列举一下this关键字常见的几种场景. 1.this代表当前对象调用成员变量和方法,也是用的最多的地 ...

  8. wab框架

    http协议 一.http简介        1.HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等).       2.HTTP是一个属于应用层的面向对象的协 ...

  9. 【转】java中静态方法和非静态方法的存储

    将某 class 产生出一个 instance 之后,此 class 所有的 instance field 都会新增一份,那么所有的 instance method 是否也会新增一份?答案是不会,我们 ...

  10. OpenStack H版与 Ceph 整合的现状

    转自:https://www.ustack.com/blog/openstack_and_ceph/ Contents 1 Ceph与Nova整合 2 Ceph与Cinder整合 3 相关Patch ...