概念
java之中,被定义在另一个类或者一个方法里面的类被称为内部类
内部类的分类
1、成员内部类
2、局部内部类
2.1、匿名内部类
3、静态内部类
成员内部类
1、语法格式:
成员内部类是最普通的内部类,它的定义位于另一个类的内部:
class Outer {
//成员内部类
class Inner {
}
}2、怎么实例化一个成员内部类?
先实例化外部对象
Outter outter = new Outter();再由外部对象去(new)实例化内部成员类:
外部类.内部类 内部类对象名 = 外部类对象.new 内部类();
Outter.Inner inner = outter.new Inner();3、特点:
成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)
4、注意:
当成员内部类拥有和外部类同名的成Dd员变量或者方法时,会发生隐藏现象,
即默认情况下访问的是成员内部类的成员。如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
栗子
package com.blog.innertClassTest;
/**
* @Author jinhuan
* @Date 2022/3/23 17:42
* Description:
* 局部内部类
*/
public class InnerClass01 {
public static void main(String[] args) {
//实例化一个局部内部类对象
InnerClass01 innerClass01 = new InnerClass01();
InnerClass01.Inner01 inner01 = innerClass01.new Inner01();
//合并步骤
//InnerClass01.Inner01 inner01 = new InnerClass01().new Inner01();
//调用内部的test方法 注意,里面修改了num 的值,调用后我们检验是否修改成功
inner01.test();
//检验外部类的私有属性num 的值是否发生变化
System.out.println("内部类修改后的num值是:"+innerClass01.num);
}
/**
* 外部类的私有属性num
* */
private int num = 10;
/**
* 外部类的say方法
* */
private void say(){
System.out.println(" I'm a Outter Class! ");
}
/**
* 内部类Ineer
* */
class Inner01{
//内部类实例访问外部类的私有属性
private void test(){
System.out.println("外部的私有属性num的值是"+num);
num += 10;
System.out.println("外部的私有属性num的值经过修改后是"+num);
//调用内外类的同名方法 发现默认调用的是内部成员自己的方法(就近原则)
System.out.print("默认调用的say方法是:");
say();
//如何使用内部类对象调用外部类的成员方法
System.out.print("调用外部同名的say方法:");
InnerClass01.this.say();
}
/**
* 外部类同名方法
* */
private void say(){
System.out.println(" I'm a Inner Class! ");
}
}
}
局部内部类
1、语法格式:
[修饰符列表] 返回值类型 方法名(形式参数列表){
class 局部内部类{
}
}2、怎样实例化一个局部内部类?
在其所属的方法作用域内,通过new关键字创建
3、注意:
局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。
4、适用场景
某个类的创建仅仅使用一次的时候
或者说为了使用某个方法我们不得不去实例化某个无用的类或者其实现类的时候
栗子1
package com.blog.innertClassTest;
/**
* @Author jinhuan
* @Date 2022/3/24 11:13
* Description:
*/
public class InnerClass02 {
static int num01 = 11;
private int num02 = 12;
public static void main(String[] args) {
int num03 = 13;
/**
* 局部内部类 Inner02
* */
class Inner02{
int num04 = 14;
/*
局部内部类和成员内部类的区别在于
局部内部类的访问仅限于方法内或者该作用域内,外部类的私有属性无法直接访问
*/
public void test(){
System.out.println("外部静态全局变量num01的值是:"+num01);
//System.out.println("外部类的私有属性num02 :"+ num02);
System.out.println("外部类的私有属性num02 : 无法直接访问");
System.out.println("和自己处在同一个作用域内的变量num03的值是:"+num03);
System.out.println("位于自己内部的变量num04的值是:"+num04);
}
}
//实例化局部内部类
Inner02 inner02 = new Inner02();
//调用局部内部类的test方法
inner02.test();
}
}
栗子2(使用场景)
接口类
package com.blog.innertClassTest;
/**
* @Author jinhuan
* @Date 2022/3/24 13:23
* Description:
* 模拟某开发场景,
* 面向接口编程:现在根据需求定义了一个人类接口
* 里面的抽象方法表示人类共有的特性,即人类的“实现着”应该会吃饭
*/
public interface Person {
void eat();
}
测试类
package com.blog.innertClassTest;
/**
* @Author jinhuan
* @Date 2022/3/24 13:26
* Description:测试类
*
*/
public class Test01 {
public static void main(String[] args) {
/*
* 现在假设有一个需求
* 我们必须要调用下面的use方法
* 但是我们没有person的实现类,而且这个方法我们只用这一次
* 怎么办?接口又没办法直接实例化!
* 去创建一个接口实现类!
* 这是必然的,但是我们有必要去单独创建一个只用一次的类吗?
* 其实没必要,局部内部类足够了
* */
/**
* 局部内部类
* */
class PersonImpl implements Person{
@Override
public void eat() {
System.out.println("我在吃东西!");
}
}
PersonImpl person = new PersonImpl();
//成功调用use方法
use(person);
}
/**
* 被调用的方法 use
* */
public static void use(Person person){
}
}
局部内部类与final关键字(重点)
在jdk1.8之前,局部内部类中只能访问final类型的变量(全局变量除外)
但是1.8版本之后,如果局部内部类中访问了某个可以访问到的变量A,将默认为其加上 final 关键字进行修饰
但是,一旦对A进行重新赋值,那么之前的访问就会出错!
因为final类型的变量不可以被重新赋值,这和局部内部类只能访问final类型的数据产生了冲突!
栗子
匿名内部类
1、语法格式:
带引用:
父类 父类引用 = new 父类构造器(参数列表)|实现接口(){
//匿名内部类的类体部分,如果是接口,需要实现它
};不带引用:
new 父类构造器(参数列表)|实现接口(){
//匿名内部类的类体部分,如果是接口,需要实现它
};2、怎样实例化一个匿名内部类?
匿名内部类在创建的时候直接通过 new 关键字被实例化
3、注意事项:
使用匿名内部类必须也仅且只能继承一个父类或者实现一个接口,二者不可兼得
匿名内部类没有class关键字
这是因为匿名内部类是直接使用new来生成一个对象的引用。当然这个引用是隐式的匿名内部类中是不能定义构造函数的
匿名内部类中不能存在任何的静态成员变量和静态方法
匿名内部类为局部内部类,所以局部内部类的所有限制同样对匿名内部类生效
匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法
匿名内部类中只能访问final型的局部变量
栗子
接口类
package com.blog.innertClassTest;
/**
* @Author jinhuan
* @Date 2022/3/24 13:23
* Description:
* 模拟某开发场景,
* 面向接口编程:现在根据需求定义了一个人类接口
* 里面的抽象方法表示人类共有的特性,即人类的“实现着”应该会吃饭
*/
public interface Person {
void eat();
}
测试类
package com.blog.innertClassTest;
/**
* @Author jinhuan
* @Date 2022/3/24 13:42
* Description:
*/
public class Test02 {
public static void main(String[] args) {
/**
* 匿名内部类
* */
//第一种创建方式 多态
Person person = new Person() {
@Override
public void eat() {
}
};
System.out.print("使用第一种方式创建的匿名类使用Use方法");
use(person);
//第二种方式
System.out.print("使用第二种方式创建的匿名类使用Use方法");
use(new Person(){
@Override
public void eat() {
}
});
}
/**
* 被调用的方法 use
* */
public static void use(Person person){
System.out.println("USE被调用!!!");
}
}
静态内部类
1、概念:
静态内部类也是定义在另一个类里面的类
不过是在类的前面多了一个 static关键字2、格式:
class Outter {
public Outter() {
}static class Inner { }
}
3、如何实例化:
外部类名.静态内部类名 静态内部类引用名 = new 外部类名.静态内部类名();
(和局部内部类不同的是不用先是实例化外部对象)4、注意:
静态内部类是不需要依赖于外部类对象的,类似于静态成员属性
它不能使用外部类的非static成员变量或者方法
class Test{
// 静态变量
static int num01;
// 该类在类的内部,所以称为内部类
// 由于前面有static,所以称为“静态内部类”
static class Inner01{
}
// 实例变量
int num02;
// 该类在类的内部,所以称为内部类,没有static叫做实例内部类。
class Inner02{
}
// 方法01
public void method01(){
// 局部变量
int num03 = 100;
// 该类在类的内部,所以称为内部类
// 局部内部类。
class Inner03{
}
}
//方法02
public void method02(){
// dmethod01()方法中的局部变量num03,在method02()中不能用
// 同理,dmethod01()方法中的局部内部类Inner03,在method02()中不能用
//局部的* 只能在其作用域中使用
}
// main方法
public static void main(String[] args) {
/**
* 匿名内部类
* */
//第一种创建方式 多态
Person person = new Person() {
@Override
public void eat() {
}
};
System.out.print("使用第一种方式创建的匿名类使用Use方法");
use(person);
//第二种方式
System.out.print("使用第二种方式创建的匿名类使用Use方法");
use(new Person(){
@Override
public void eat() {
}
});
}
/**
* 被调用的方法 use
* */
public static void use(Person person){
System.out.println("USE被调用!!!");
}
}
// 人类的接口
interface Person{
//抽象方法
void eat();
}
以上均为本人个人观点,借此分享。如有不慎之处,劳请各位批评指正!鄙人将不胜感激并在第一时间进行修改!😄😄😄