首页 > 编程语言 >Java学习笔记(十二)

Java学习笔记(十二)

时间:2023-08-17 11:07:08浏览次数:52  
标签:部类 Java 内部 静态 成员 十二 笔记 new out

7.5 内部类

7.5.1 内部类概述

1、什么是内部类?
顾名思义:一个类里面的类称为内部类。
例如:
class Outer{   //相对的,它是外部类
    class Inner{ //内部类

    }
}

2、为什么要用内部类?
实现高内聚低耦合的开发原则。
好处:
(1)内部类,可以被限定在外部类中使用
(2)内部类和外部类可以互相访问对方的私有的成员

例如:
    设计一些数据结构,这些数据结构是单链表、双链表、二叉树等等。

class SingleLinked{ //单链表

    private class Node{
        Object data;//元素
        Node next;//下一个元素的地址
    }
}

class LinkedList{
    private class Node{
        Node previous;//上一个元素的地址
        Object data;//元素
        Node next;//下一个元素的地址
    }
}
class Tree{
    private class Node{
        Node parent;//父结点的地址
        Object data;//元素
        Node left;//左结点的地址
        Node right;//右结点的地址
    }
}

3、内部类的形式
(1)成员内部类:声明在外部类中,在方法外面
A:静态成员内部类
B:非静态成员内部类

(2)局部内部类:声明在外部类的方法中
A:有名字的局部内部类
B:匿名的局部内部类

4、学习内部类的技巧
内部类也是类,从类的角度观察它
内部类是在外部类的里面,要么作为外部类的成员,要么作为外部类某个方法的一个局部结构,从这个角度观察它

Java学习笔记(十二)_内部类

7.5.2 静态内部类

一、静态内部类

1、语法结构

【修饰符】 class 外部类名{

   【其他修饰符】 static class 静态内部类名{


   }

}


2、从类的角度观察

(1)有自己的字节码文件吗?有,外部类名$静态内部类名.class

(2)是否可以继承自己的父类,实现自己的父接口呢?可以

   

(3)是否可以有自己的类成员

A:成员变量:静态变量、实例变量

B:成员方法:静态变量、实例方法

C:构造器:无参构造、有参构造

D:代码块:静态代码块、非静态代码块(如果需要可以加,但是一般很少)

E:内部类:可以有(一般不会写内部类的内部类)

   

(4)静态内部类也可以是抽象类

(5)静态内部类是可以new对象(只要不是抽象的,就可以new对象)


3、从它是外部类的成员角度

(1)修饰符:public、protected、缺省、private、static(一定有)、abstract、final

   

(2)在静态内部类中可以直接使用外部类的成员吗,包括私有的,静态非静态的?

可以用私有的,静态的,

但不能直接使用外部类的非静态成员。

   

(3)反过来,外部类是否可以直接使用静态内部类的所有成员呢,包括私有的,静态非静态的?

可以,但是要注意,

外部类使用静态内部类的非静态成员,需要先创建静态内部类的对象,然后通过“静态内部类对象.非静态成员”

外部类使用静态内部类的静态成员,需要通过“静态内部类名.静态成员”方式

   

(4)在外部类的外面使用静态内部类,可以吗?

可以,但是要注意权限修饰符问题。

而且静态内部类一定是依赖于外部类的,所以"外部类名.静态内部类名"

   

(5)在外部类的外面是否可以调用静态内部类的成员?

可以,但是要注意权限修饰符问题。

使用静态内部类的非静态成员,需要先创建静态内部类的对象,然后通过“静态内部类对象.非静态成员”

使用静态内部类的静态成员,需要通过“外部类名.静态内部类名.静态成员”方式

   

(6)当外部类的成员和静态内部类的成员重名了,怎么办?

和外部类的静态成员重名,通过“外部类名.静态成员”区分即可。

public class TestStaticInnerClass {
    public static void main(String[] args) {
        Outer.Inner in = new Outer.Inner();
        System.out.println(in.a);
        System.out.println(Outer.Inner.b);
        System.out.println("--------------");
        in.method();
    }
}

class Outer{
    int a = 1;
    static int b = 2;
    static class Inner {
         int a = 3;
         static int b = 4;

         public void method(){
             System.out.println("内部类的a = " + a);
             System.out.println("内部类的b = " + b);
//             System.out.println("外部类的a = " + a);//不可以
             System.out.println("外部类的b = " + Outer.b);
         }
    }

    public void outMethod(){
        Inner obj = new Inner();
        System.out.println("内部类的a = " + obj.a);
        System.out.println("内部类的b = " + Inner.b);
    }
}

Java学习笔记(十二)_外部类_02

7.5.3 非静态内部类

一、非静态内部类

1、语法结构

【修饰符】 class 外部类名{

   【其他修饰符】 class 非静态内部类名{


   }

}


2、从类的角度观察

(1)有自己的字节码文件吗?有,外部类名$非静态内部类名.class

(2)是否可以继承自己的父类,实现自己的父接口呢?可以

(3)是否可以有自己的类成员

A:成员变量:实例变量

B:成员方法:实例方法

C:构造器:无参构造、有参构造

D:代码块:非静态代码块(如果需要可以加,但是一般很少)

E:内部类:可以有(一般不会写内部类的内部类)


结论:非静态内部类中不允许有静态成员。


(4)非静态内部类也可以是抽象类

(5)非静态内部类是可以new对象(只要不是抽象的,就可以new对象)


3、从它是外部类的成员角度

(1)修饰符:public、protected、缺省、private、abstract、final

(2)在非静态内部类中可以直接使用外部类的成员吗,包括私有的,静态非静态的?

可以用私有的,静态的,非静态,没有限制。


(3)反过来,外部类是否可以直接使用非静态内部类的所有非静态的成员呢,包括私有的?

可以。只不过需要创建非静态内部类的对象。


(4)在外部类的外面使用非静态内部类,可以吗?

可以,但是要注意权限修饰符问题。

A:非静态内部类一定是依赖于外部类的,所以"外部类名.非静态内部类名"

B:非静态内部类还要依赖于外部类的对象,因为它是外部类的非静态成员。

   要创建非静态内部类的对象,必须先有外部类的对象。


   方式一:

       Outer out = new Outer();//外部类的对象

       Outer.Inner in = out.new Inner();//创建非静态内部类的对象,依赖于外部类的对象


   方式二:

       Outer out = new Outer();//外部类的对象

       Outer.Inner in2 = out.getInner();//调用外部类的某个方法,得到非静态内部类的对象

       要注意外部类中得所有一个getInner()方法,里面会返回Inner对象才可以。


(5)在外部类的外面是否可以调用非静态内部类的非静态成员?

可以,但是要注意权限修饰符问题。

   先创建外部类对象,再创建非静态内部类的对象,再通过“非静态内部类的对象.非静态成员”


(6)当外部类的成员和非静态内部类的成员重名了,怎么办?

A:和外部类的静态成员重名,通过“外部类名.静态成员”区分即可。

B:和外部类的非静态成员重名,通过“外部类名.this.非静态成员”区分即可。

public class TestNonStaticInnerClass {
    public static void main(String[] args) {
        Outer out = new Outer();//外部类的对象
        Outer.Inner in = out.new Inner();//创建非静态内部类的对象,依赖于外部类的对象
        Outer.Inner in2 = out.getInner();//调用外部类的某个方法,得到非静态内部类的对象

        in.inMethod();
        in2.inMethod();
    }
}
class Outer{
    private int a = 1;
    private static int b = 2;

    class Inner{
        private int a = 3;
        private int b = 4;

       public void inMethod(){
           System.out.println("非静态内部类的非静态方法");

           System.out.println("内部类的a = " + a);
           System.out.println("内部类的b = " + b);
/*           Outer out = new Outer();
           System.out.println("外部类类的a = " + out.a);//可以*/
           System.out.println("外部类类的a = " + Outer.this.a);//可以更直接
           System.out.println("外部类类的b = " + Outer.b);

           System.out.println("内部类的a = " + this.a);
           /*
           这个方法中有两个当前对象:
           一个是内部类自己的当前对象
           另一个是外部类的当前对象
           因为调用inMethod(),new了两个对象
            */
       }
    }

    public Inner getInner(){
        return new Inner();
    }
}

Java学习笔记(十二)_静态成员_03

7.5.4 静态内部类和非静态内部类的对比


静态内部类(静态成员内部类)

非静态内部类(非静态成员内部类)

字节码文件名

外部类名$成员内部类名.class

同左

继承父类实现父接口

可以

同左

内部类自己的成员

所有成员都可以

==不能有自己的静态成员==

是否可以是抽象类

可以

同左

是否可以new对象

同左

同左

修饰符

public、protected、缺省、private、abstract、final、static

==没有static==,其他同左

直接使用外部类的静态成员

可以

同左

直接使用外部类的非静态成员

==不可以==

可以

外部类使用内部类的静态成员

可以

==没有静态成员==

外部类使用内部类的非静态成员

可以,创建内部类的对象再用

同左

依赖于外部类

依赖

同左

依赖于外部类的对象

不依赖

依赖

在外部类的外面使用内部类声明变量

外部类名.内部类名 变量;

同左

在外部类的外面创建内部类的对象

外部类名.静态内部类名 变量 = new 外部类名.静态内部类名();

(1)外部类名 变量1 = new 外部类名();

(2)外部类名.非静态内部类名 变量 = ==变量1==.new 非静态内部类名();

在外部类的外面使用内部类的静态成员

外部类名.静态内部类名.静态成员

==没有静态成员==

在外部类的外面使用内部类的非静态成员

先创建内部类对象,再用“内部类对象.非静态成员”

同左

内部类中成员和外部类的静态成员重名

外部类名.静态成员

同左

内部类中成员和外部类的非静态成员重名

不存在(因为无法直接使用外部类的非静态成员)

==外部类名.this.非静态成员==

如何选择?

当使用这个内部类时,不依赖于外部类对象时,就选静态内部类

当使用这个内部类时,==依赖于外部类对象==时,就选非静态内部类

7.5.5 局部内部类

一、局部内部类(很少用,了解 * )

1、语法结构

【修饰符】 class 外部类名{

   【修饰符】 返回值类型 方法名(【形参列表】){

       【其他修饰符】 class 局部内部类名{


       }

   }

}


理论上,代码块(静态代码块或非静态代码块)、成员方法的方法体、构造器的方法体中都可以声明局部内部类,

但是通常的局部内部类是在成员方法的方法体中。


2、从类的角度观察

(1)有自己的字节码文件吗?有,外部类名$编号局部内部类名.class


为什么有编号?因为局部内部类可以重名。


(2)是否可以继承自己的父类,实现自己的父接口呢?可以

(3)是否可以有自己的类成员

A:成员变量:实例变量

B:成员方法:实例方法

C:构造器:无参构造、有参构造

D:代码块:非静态代码块(如果需要可以加,但是一般很少)

E:内部类:可以有(一般不会写内部类的内部类)


结论:局部内部类中不允许有自己静态成员。


(4)局部内部类也可以是抽象类

(5)局部内部类是可以new对象(只要不是抽象的,就可以new对象)


3、从它是外部类的局部结构角度

(1)修饰符:abstract、final


(2)在局部内部类中可以直接使用外部类的成员吗,包括私有的,静态非静态的?

可以用私有的,静态的。

但是非静态是否能访问受所在方法是否静态的限制,即  局部内部类在外部类的静态方法中,只能访问外部类的静态成员。

                                           局部内部类在外部类的非静态方法中,可以访问外部类的所有成员,包括静态和非静态的。



(3)反过来,外部类是否可以直接使用局部内部类的所有非静态的成员呢,包括私有的?

可以。只不过需要创建局部内部类的对象,并且要注意"作用域"。


(4)在外部类的外面使用局部内部类,可以吗?不允许



(5)在外部类的外面是否可以调用局部内部类的非静态成员?

可以,但是只能通过多态引用的方式调用,所以意味着不能调用局部内部类扩展的成员,

只能调用父类声明的成员,或子类重写的成员。


(6)当外部类的成员和局部内部类的成员重名了,怎么办?

A:和外部类的静态成员重名,通过“外部类名.静态成员”区分即可。

B:和外部类的非静态成员重名,通过“外部类名.this.非静态成员”区分即可。



(7)在局部内部类中还可以使用所在方法或代码块的局部变量,但是这个局部变量必须是final的。

JDK1.8之前,必须手动加final

JDK1.8之后,自动加final


为什么要加final呢?

因为,在局部内部类中使用的这个变量,本质上已经不是外部类的这个局部变量了。

而是有一个隐形的成员变量接收了这个局部变量的值。

但是,从代码的阅读角度来说,似乎它们就是同一个,为了避免引起不必要的误解,干脆规定它必须是final的,

不能修改的,那么就算大家认为它们是同一个也没有关系。

public class TestLocalInner {
//    private static Father f;

    public static void main(String[] args) {
//        Inner in = new Inner();//超过作用域了,不能直接使用Inner类

//        outMethod();
//        f.inMethod();

        Father subClassOfFather = getSubClassOfFather();//多态引用
        /*
        通过外部类的一个方法,返回内部类的对象,
        接收这个内部类的对象,用内部类的父类或父接口的变量接收。
         */
        subClassOfFather.inMethod();
    }

    public static Father getSubClassOfFather(){
        final int num = 10;//局部变量

        class Inner extends Father{//局部内部类
            private int inA;

            public void inMethod(){
//                System.out.println("outA = " + outA);//因为outMethod()是静态的,不能使用外部类的非静态outA
                System.out.println("outB = " + outB);
                System.out.println("num = " + num);
            }
        }
        return new Inner();
    }

    private int outA;
    private static int outB;

    public static void outMethod(){
        int a = 1;//局部变量
        class Inner extends Father{//局部内部类
            private int inA;

            public void inMethod(){
//                System.out.println("outA = " + outA);//因为outMethod()是静态的,不能使用外部类的非静态outA
                System.out.println("outB = " + outB);
            }
        }

        Inner obj = new Inner();
//        f = obj;
        System.out.println("inA = " + obj.inA);
        obj.inMethod();
    }

    public void outTest(){
        class Inner{
            public void inMethod(){
                System.out.println("outA = " + outA);
                System.out.println("outB = " + outB);
            }
        }
    }
}

abstract class Father{
    public abstract void inMethod();
}

Java学习笔记(十二)_内部类_04

public class Outer {
    public static void main(String[] args) {
        int a = 1;
        class Inner{
            /*private int a;
            public Inner(int a){
                this.a = a;
            }*/
            public void method(){
                System.out.println(a);
            }
        }
    }
}

Java学习笔记(十二)_静态成员_05

7.5.6 成员内部类和局部内部类的对比


静态内部类(静态成员内部类)

非静态内部类(非静态成员内部类)

局部内部类

字节码文件名

外部类名$成员内部类名.class

同左

外部类名$==编号==成员内部类名.class

继承父类实现父接口

可以

同左

同左

内部类自己的成员

所有成员都可以

==不能有自己的静态成员==

==不能有自己的静态成员==

是否可以是抽象类

可以

同左

同左

是否可以new对象

同左

同左

同左

修饰符

public、protected、缺省、private、abstract、final、static

==没有static==,其他同左

只能abstract或final,或没有

直接使用外部类的静态成员

可以

同左

同左

直接使用外部类的非静态成员

==不可以==

可以

要看所在方法是否是静态的,如果是静态方法就不可以,如果是非静态方法,就可以。

外部类使用内部类的静态成员

可以

==没有静态成员==

==没有静态成员==

外部类使用内部类的非静态成员

可以,创建内部类的对象再用

同左

同左,并要注意==作用域==

依赖于外部类

依赖

同左

同左

依赖于外部类的对象

不依赖

依赖

要看所在方法是否是静态的,如果是静态方法就不依赖,如果是非静态方法,就依赖。

在外部类的外面使用内部类声明变量

外部类名.内部类名 变量;

同左

==不可以==

在外部类的外面创建内部类的对象

外部类名.静态内部类名 变量 = new 外部类名.静态内部类名();

(1)外部类名 变量1 = new 外部类名();

(2)外部类名.非静态内部类名 变量 = ==变量1==.new 非静态内部类名();

只能通过内部类的父类或父接口的变量,接收内部类的对象,局部内部类的对象只能在所在方法中创建。

在外部类的外面使用内部类的静态成员

外部类名.静态内部类名.静态成员

没有静态成员====

==没有静态成员==

在外部类的外面使用内部类的非静态成员

先创建内部类对象,再用“内部类对象.非静态成员”

同左

只能多态引用的形式访问,访问继承的或重写的成员,不能是自己扩展的成员。

内部类中成员和外部类的静态成员重名

外部类名.静态成员

同左

同左

内部类中成员和外部类的非静态成员重名

不存在(因为无法直接使用外部类的非静态成员)

==外部类名.this.非静态成员==

同中

如何选择?

当使用这个内部类时,不依赖于外部类对象时,就选静态内部类

当使用这个内部类时,==依赖于外部类对象==时,就选非静态内部类

当这个内部类仅限于当前方法有用,就可以用局部内部类(很少很少用)

使用外部类的局部变量

不可以

不可以

只能用当前方法final修饰的局部变量

7.5.7 匿名内部类

1、首先,匿名内部类也是局部内部类,只是它没有名字。

2、语法格式:

(1)new 父类(){


}

(2)new 父类(实参列表){


}

(3)new 父接口(){


}


3、特殊

(1)这个内部类没有名字,所以必须在声明的同时,就创建它唯一的对象。

(2)这里new对象,指定了父类名或父接口名,指明了它是从哪个类别派生出来的。

匿名内部类又称为匿名子类或匿名实现类。

(3)因为匿名,所以这个类无法写构造器,只有默认的无参构造。

(4)因为没有class关键字等声明形式,所以匿名内部类没有任何修饰符。


4、从类的角度

(1)有自己的字节码文件吗?有,外部类名$编号.class

(2)是否可以继承自己的父类,实现自己的父接口呢?可以

其他内部类可以同时继承父类又实现接口,

但是匿名内部类只能指定父类或父接口。

new 父类(【实参列表】){} 指定父类

new 父接口(){}指定父接口


(3)是否可以有自己的类成员

A:成员变量:实例变量

B:成员方法:实例方法

C:构造器:默认的无参构造(无法手动编写构造器)

D:代码块:非静态代码块(如果需要可以加,但是一般很少)

E:内部类:可以有(一般不会写内部类的内部类)


结论:匿名内部类中不允许有静态成员,也不能手动编写构造器。


但是,一般很多在匿名内部类中写很多成员,而且一般也不扩展自己的成员,

通常都是重写父类或父接口的方法。

(4)匿名内部类不可以是抽象类,不能加修饰符abstract

(5)匿名内部类是可以new对象:一定会有对象,而且在声明类的同时就创建了唯一对象了


5、如何使用匿名内部类?

(1)匿名子类的匿名对象.方法

new 父类(【实参列表】){....}.方法();


(2)多态引用

父类 变量 = new 父类(【实参列表】){....};

变量.方法();  //只能调用重写的方法


父接口 变量 = new 父接口(){....};

变量.方法();  //只能调用重写的方法


(3)匿名子类或匿名实现类的对象作为另一个方法调用的实参


6、语法格式说明:

(1)new 父类(){


}

表示匿名子类的构造器首行是 super();,调用父类的无参构造。

(2)new 父类(实参列表){


}

表示匿名子类的构造器首行是 super(实参列表);,调用父类的有参构造。

(3)new 父接口(){


}

表示匿名子类的构造器首行是 super();,调用父类的无参构造。它的父类是默认父类Object类。

public class TestNoNameInnerClass {
    public static void main(String[] args) {
        new Object();//创建的是Object类的对象

        new Object(){

        };//创建的是Object的匿名子类的对象

        System.out.println("------------下面演示使用---------------");
        new Object(){
            public void method(){
                System.out.println("匿名内部类扩展的自己的方法");
            }
        }.method();
        //Object父类的匿名子类的匿名对象,调用method方法

        Father f = new Father() {//创建Father类的匿名子类的对象
            @Override
            public void method() {
                System.out.println("重写父类的抽象方法");
            }
        };//多态引用
        f.method();

        Flyable fObj = new Flyable() {//创建的是Flyable接口的匿名实现类的对象
            @Override
            public void fly() {
                System.out.println("重写接口的抽象方法");
            }
        };
        fObj.fly();

        test(new Father() {
            @Override
            public void method() {
                System.out.println("另一个匿名子类的对象重写method方法");
            }
        });

        new Mother("虎妞"){
            @Override
            public void method() {
                System.out.println("重写方法" + info);
            }
        }.method();
    }

    public static void test(Father f){
        f.method();
    }
}
abstract class Father{
    public abstract void method();
}

interface Flyable{
    void fly();
}

abstract class Mother{
    protected String info;

    public Mother(String info) {
        this.info = info;
    }

    public abstract void method();
}

标签:部类,Java,内部,静态,成员,十二,笔记,new,out
From: https://blog.51cto.com/u_16213911/7119220

相关文章

  • Java中Date方法详解
    先进行专栏介绍本专栏是自己学Java的旅途,纯手敲的代码,自己跟着黑马课程学习的,并加入一些自己的理解,对代码和笔记进行适当修改。希望能对大家能有所帮助,同时也是请大家对我进行监督,对我写的代码进行建议,互相学习。Date方法Date类是用于表示日期和时间的类。它提供了一系列的方......
  • PyTorch神经网络工具箱-新手笔记
    训练模型构建模型后,接下来就是训练模型。PyTorch训练模型的主要步骤包括加载和预处理数据集、损失计算、定义优化算法、反向传播、参数更新等主要步骤。1)加载和预处理数据集:可以使用PyTorch的数据处理工具,如torch.utils和torchvision等。2)定义损失函数:通过自定义的方法或使用PyTorc......
  • Java导出Excel带格式工具类
    Java导出Excel里面有具体内容,带有格式。可以创建工具类直接去使用/***通用模版下载*@paramoutputStream以流的形式输出到浏览器*@paramexcelName下载excel的文件名称*@paramWaring提示语言*@paramtitleS标题列*@paramcontentS......
  • Java导出Excel带格式工具类
    Java导出Excel里面有具体内容,带有格式。可以创建工具类直接去使用/***通用模版下载*@paramoutputStream以流的形式输出到浏览器*@paramexcelName下载excel的文件名称*@paramWaring提示语言*@paramtitleS标题列*@paramcontentS......
  • Vue学习笔记:Vuex Part03 Action
    定义ActionAction类似于mutation,不同在于:Action提交的是mutation,而不是直接变更状态。Action可以包含任意异步操作。示例conststore=createStore({state:{count:0},mutations:{increment(state){state.count++}},actions:{......
  • mormot2 笔记(二) Http服务的简单搭建
    mormot2框架中有个THttpServer类,它有一个Router属性,定义如下:propertyRouter:TUriRouterreadfRoute;Router是添加路由的入口点,它有和http协议对应的get,post,put,delete等方法,这些方法可以添加路由,下面常用的get方法定义。procedureGet(constaUri:RawUtf8;......
  • Java应用堆外内存泄露问题排查
    问题是怎么发现的最近有个java应用在做压力测试压测环境配置:CentOS系统4核CPU8g内存jdk1.6.0_25,jvm配置-server-Xms2048m-Xmx2048m出现问题如下执行300并发,压测持续1个小时后内存使用率从20%上升到100%,tps从1100多降低到600多。排查问题的详细过程首先使用top命令查......
  • java高级工程师需要掌握的知识
          结语学习没有捷径,一步一个脚印! ......
  • JavaScript中的标识符和保留字
    标识符。简单地说,标识符就是一个名字。在JavaScript中,标识符用于为JavaScript代码中的常量、变量、属性、函数和类命名,还可用于为某些循环提供标签。JavaScript标识符必须以字母、下划线(_)或美元符号($)开头。后续字符可以是字母、数字、下划线或美元符号(数字不能作为第一个字符,以区......
  • javaSpring操作事务
    1.什么是事务简单理解你:事务就是将一系列动作看成是一次工作单元,又涉及到套娃了举个栗子:转账操作,张三向李四转账100块钱,在转账途中,突然停电,但是账单已经发出去了,这个时候如果没有事务的话,那么张三向李四转账的100块钱将不翼而飞事务的作用,将张三和李四的的转账看成一个动作,要......