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. springboot---aop切片编程

    1.介绍 面向切面编程,关注点代码与业务代码分离,就是给指定方法执行前执行后..插入重复代码 关注点:重复代码 切面:被切面的类 切入点:执行目标对象方法,动态植入切片代码 2.部署步骤 2.1:添加 ...

  2. CodeForces 266E More Queries to Array...(线段树+式子展开)

    开始觉得是规律题的,自以为是的推了一个规律,结果测试数据都没过....看了love神的博客才发现只是把式子展开就找到规律了.不过挺6的是我虽然想错了,但是维护的的东西没有错,只是改改(改了进两个小时好 ...

  3. 《Think in Java》(八)多态

    "封装"通过合并特征和行为来创建新的数据类型: "实现隐藏"通过将细节"私有化"把接口和实现分离开来: "多态"消除类型 ...

  4. element-ui dialog组件添加可拖拽位置 可拖拽宽高

    edge浏览器下作的gifhttp://www.lanourteam.com/%E6... 有几个点需要注意一下 每个弹窗都要有唯一dom可操作 指令可以做到 拖拽时要添加可拖拽区块 header 由 ...

  5. deep learning (六)logistic(逻辑斯蒂)回归中L2范数的应用

    zaish上一节讲了线性回归中L2范数的应用,这里继续logistic回归L2范数的应用. 先说一下问题:有一堆二维数据点,这些点的标记有的是1,有的是0.我们的任务就是制作一个分界面区分出来这些点. ...

  6. oracle后台进程简介

    一:database write--数据写入  DBWR    作用:把SGA中被修改的数据同步到磁盘文件中.保证Buffer Cache中有足够的空闲数据块数量.    PS:如果LGWR出现故障, ...

  7. LeetCode OJ:Populating Next Right Pointers in Each Node II(指出每一个节点的下一个右侧节点II)

    Follow up for problem "Populating Next Right Pointers in Each Node". What if the given tre ...

  8. 使用BackgroundWorker组件

    BackgroundWorker 组件用来执行诸如数据库事务.文件下载等耗时的异步操作. 开始 在应用程序中添加一个BackgroundWorker实例,如果用的是VS,可以从工具上直接拖到应用程序: ...

  9. 2018.7.2 AK22 不良品分析

    a 电路 b 软件 STM32-工业炉温控制器程序 c . layout 不良分析: 1测各模块电压 12V  ok 5V  ok 3.3V  ok 2跟换MCU 给MCU烧程序 ok 3测量MCU晶 ...

  10. 7.MySQL优化---存储过程和存储函数

    转自互联网. 当一个大型系统在建立时,会发现,很多的SQL操作是有重叠的,个别计算是相同的,比如:业务系统中,计算一张工单的计算方式.当遇到这些情况时,我们运用存储过程就是一个非常棒的优化啦.那么,什 ...