一、简介

描述:

  • 很多时候我们创建类的对象的时候并不需要使用很多次,每次只使用一次,这个时候我们就可以使用内部类了。
  • 内部类不是在一个java源文件中编写两个平行的类,而是在一个类的内部再定义另外一个类。 我们可以把外边的类称为外部类,在其内部编写的类称为内部类。

分类:

  1. 成员内部类
  2. 静态内部类
  3. 局部内部类
  4. 匿名内部类

内部类通用用法:

  • 要想访问内部类中的内容,必须通过外部类或外部类对象
  • 内部类可以访问外部类的所有访问权限的属性和方法,包括私有的成员变量、方法。原理就是在通过外部类对象实例化内部类对象时,外部类对象把自己的引用传进了内部类,使内部类可以用通过'外部类名.this'去调用外部类的属性和方法。一般都是隐式调用了,但是当内部类中有属性或者方法名和外部类中的属性或方法名相同的时候,就需要通过显式调用'外部类名.this.外部类属性名'了。

二、成员内部类

描述:

  • 成员内部类又叫实例内部类、非静态内部类。
  • 一个类在另一个类的内部,那么想要使用这个内部类,就必须先要有外部类的一个实例对象,然后在通过该对象去使用内部类

注意:

  • 成员内部类中可以访问外部类的所有属性和方法,包括私有的成员变量、方法。
  • 成员内部类中不能写静态的属性和方法
  • 实例化内部类,首先需要实例化外部类,通过外部类去调用内部类
  • 如果内部类中的变量名和外部类的成员变量名一样,在内部类中,要通过'外部类名.this.外部类属性名'来访问外部类属性,通过'this.内部类属性名'来访问内部类属性

示例:

class Outer {
private int id;
private String name = "outer"; public void out() {
System.out.println("这是外部类方法");
} class Inner {
private int id = 8; public void in() {
System.out.println("这是内部类方法");
} public void test() {
System.out.print(name + " " + Outer.this.id + " " + id);
}
}
} public class Test {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.test();//outer 0 8
}
}

三、静态内部类

描述:

  • 使用'static'修饰的内部类就叫静态内部类
  • 静态内部类是外部类的静态成员,从属于外部类,不从属于外部类对象。

特点:

  • 静态内部类能够直接被外部类给实例化,不需要使用外部类对象。
  • 静态内部类中可以声明静态方法和静态变量
  • 静态内部类中没有外部类对象的引用,所以不能使用外部类的非静态属性和方法

示例:

public class Test {
private String name;
private static int age; public void run() {
} public static void go() {
} private static class StaticInnerClass {
private String name;
private static int age; public void test1(String name) {
System.out.println(name + " " + this.name + " " + StaticInnerClass.age + " " + Test.age);
/*
静态内部类不能访问外部类非静态属性
System.out.println(Test.this.name);
*/
Test.go();
/*
静态类不能访问非静态方法
Test.this.run();
*/
} public static void test2(String name) {
/* 内部类的静态方法只能访问自己和外部类的静态属性和方法 */
System.out.print(name + " " + StaticInnerClass.age + " " + Test.age);
/*
内部类的静态方法不能访问外部类的非静态属性
System.out.println(Test.this.name);
*/
/*
内部类的静态方法里面连自己类的非静态属性都不能访问
System.out.println(this.name);
*/
Test.go();
/*
内部类的静态方法不能访问非静态方法
Test.this.run();
*/
}
} /* 外部类访问静态内部类 */
public static void main(String[] args) {
/* 静态的内部类不需要依赖外部类,所以不用new外部类对象 */
StaticInnerClass sic = new StaticInnerClass();
/* 内部类对象调用内部类成员变量和成员方法 */
sic.name = "张三";
sic.test1("李四");//李四 张三 0 0
/* 内部类调用内部类静态变量和静态方法 */
StaticInnerClass.age = 10;
StaticInnerClass.test2("王五");//王五 10 0
}
}

四、局部内部类

描述:

  • 局部内部类是在方法内部声明的类
  • 局部内部类只能在所在的方法中使用,生命周期相当于一个局部变量,只能在方法体里。
  • 局部内部类的作用跟在成员内部类差不多,也可以访问所在外部类的成员变量及方法。

注意:

  • 局部内部类不能通过外部类对象直接实例化,而是在方法中实例化出自己来,然后通过内部类对象调用自己类中的方法。
  • 局部内部类中如果要访问该内部类所在方法中的局部变量,那么这个局部变量就必须是'final'修饰的。'final'修饰的变量会变为常量,在常量池中放着。如果不变为常量,当局部内部类被实例化后,方法弹栈,局部变量随着跟着消失,这个时候局部内部类对象想去调用该局部变量,就会出错,因为该局部变量已经没了。当局部变量变为常量后,就会将其加入常量池中,即使方法弹栈了,该局部变量还在常量池中呆着,局部内部类也就是够调用。所以局部内部类想要调用局部变量时,需要使用'final'修饰,不使用,编译都通不过。

示例:

public class Test {
private String name;
private static int age; public void run() {
} public static void go() {
} public void test() {
final String myName = "王五";
/* 局部内部类要定义在方法中 */
class LocalInnerClass {
private String name;
/*
不能定义静态属性
private static int age;
*/
public void test(String name) {
System.out.println(name + " " + this.name + " " + myName + " " + Test.this.name);
Test.this.run();
Test.go();
}
} LocalInnerClass lic = new LocalInnerClass();
lic.name = "张三";
lic.test("李四");//李四 张三 王五 null
} public static void main(String[] args) {
new Test().test();
}
}

五、匿名内部类

描述:

  • 匿名内部类是最常用的一种内部类。
  • 匿名内部类是只会使用一次的类。那么就不需要先定义一个类,而是等到需要用的时候,再临时实现并使用这个类。
  • 匿名内部类需要依托于其他类或者接口来创建。如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类;如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。
  • 匿名内部类的声明必须是在使用'new'关键字的时候。匿名内部类的声明及创建对象必须一气呵成,并且之后不能反复使用,因为没有名字。

注意:

  • 匿名内部类除了依托的类或接口之外,不能指定继承或者实现其他类或接口,同时也不能被其他类所继承,因为没有名字。
  • 匿名内部类中,我们不能写出其构造器,因为没有名字。
  • 匿名内部类中,除了重写或实现依托的类或接口的方法外,一般不会再写其他独有的方法,因为从外部不能直接调用到(间接是调用到的)。

语法:

new Class(){
/* 重写类里的方法,或者实现类或接口中的抽象方法。 */
}

示例:

interface Person {
public void say();
} public class Test {
public static void main(String[] args) {
/*
new Class(){}的作用就是将接口给实现了,只不过这里实现该接口的是一个匿名类,也就是说这个类没名字,只能使用这一次。
我们知道了这是一个类,将其new出来,就能获得一个实现了Person接口的类的实例对象,通过该实例对象,就能调用该类中的方法了。
因为该匿名类是在一个类中实现的,所以叫其匿名内部类。
*/
new Person() {
public void say() {
System.out.println("实现了Person接口的方法");
}
}.say();//实现了Person接口的方法
}
}

Java基本概念:内部类的更多相关文章

  1. JAVA 第二天 内部类

    package com.company; /** * Created by Administrator on 2016/8/23. */ public class Outter {//生成的字节码文件 ...

  2. 【转】Java中的内部类和匿名类

       Java内部类(Inner Class),类似的概念在C++里也有,那就是嵌套类(Nested Class),乍看上去内部类似乎有些多余,它的用处对于初学者来说可能并不是那么显著,但是随着对它的 ...

  3. Java中的内部类怎么用

    一.为什么需要内部类?java内部类有什么好处?为什么需要内部类? 首先举一个简单的例子,如果你想实现一个接口,但是这个接口中的一个方法和你构想的这个类中的一个方法的名称,参数相同,你应该怎么办?这时 ...

  4. [java] 深入理解内部类: inner-classes

    [java] 深入理解内部类: inner-classes // */ // ]]>   [java] 深入理解内部类: inner-classes Table of Contents 1 简介 ...

  5. Java中的内部类(成员内部类、静态内部类、局部内部类、匿名内部类)

    Java中的内部类(成员内部类.静态内部类.局部内部类.匿名内部类) 神话丿小王子的博客主页 我们先看这样一段话:人是由大脑.肢体.器官等身体结果组成.而组成我们人体的心脏它也有自己的属性和行为(血液 ...

  6. java基础之 内部类

    Java中的内部类共分为四种: 静态内部类static inner class (also called nested class) 成员内部类member inner class 局部内部类loca ...

  7. java 笔记(2) —— 内部类的作用

    一.内部类简介 个人觉得内部类没多少研究价值,GUI中的事件响应算是非常典型的应用了. Java内部类其实在J2EE编程中使用较少,不过在窗口应用编程中特别常见,主要用来事件的处理.其实,做非GUI编 ...

  8. Java基础(53):内部类(转)

    java中的内部类总结 内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类 如同一个人是由大脑.肢体.器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行 ...

  9. Java多线程概念简介 多线程中篇(一)

    Java的线程与操作系统的线程   在线程的相关介绍中,有讲到“线程的实现”分为三种:内核支持,用户级以及两者混合.(这只是一种简要的分类) Java线程在JDK1.2之前,是用户线程实现的 而在JD ...

  10. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

随机推荐

  1. docker(2)CentOS 7安装docker环境

    前言 前面一篇学了mac安装docker,这篇来学习在linux上安装docker 环境准备 Docker支持以下的CentOS版本,目前,CentOS 仅发行版本中的内核支持 Docker. Doc ...

  2. Codeforces Round #651 (Div. 2) D. Odd-Even Subsequence(二分)

    题目链接:https://codeforces.com/contest/1370/problem/D 题意 给出一个含有 $n$ 个数的数组 $a$,从中选出 $k$ 个数组成子序列 $s$,使得 $ ...

  3. cmath取整函数

    #include <iostream> #include <cmath>//头文件 using namespace std; int main () { double n; c ...

  4. Codeforces Round #651 (Div. 2) A. Maximum GCD (思维)

    题意:在\(1\)~\(n\)中找两个不相等的数使得他们的\(gcd\)最大. 题解:水题,如果\(n\)是偶数,那么一定取\(n\)和\(n/2\),\(n\)是奇数的话,取\(n-1\)和\((n ...

  5. (数据科学学习手札106)Python+Dash快速web应用开发——回调交互篇(下)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  6. windows7 更新失败,无法开机处理方法

    记录一次今天同事笔记本无法开机的故障处理 windows7系统,安装更新失败,无法开机,卡在配置更新界面 处理方法,强制关机,开机按F8,进入安全模式,安全模式还会卡在配置更新界面,但是卡一会会进入系 ...

  7. vscode remote Development ssh targets 连接腾讯云

    配置 本地安装 插件 remote development 点击左侧,选择ssh 点击设置按钮,选择ssh配置文件 配置举例 ``` Host tencentcloud     HostName    ...

  8. github 无法访问

    描述: 1. ping 丢失 100% 2. git 失败 Failed to connect to github.com port 443: Timed out 3.打开网站 超时 解决: http ...

  9. 蓝桥杯-摔手机问题【dp】

    非常详细的题解:戳这里 例题:poj-3783 Balls Balls Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 115 ...

  10. WMI在渗透测试中的重要性

    0x01 什么是wmi WMI可以描述为一组管理Windows系统的方法和功能.我们可以把它当作API来与Windows系统进行相互交流.WMI在渗透测试中的价值在于它不需要下载和安装, 因为WMI是 ...