JAVA第八章总结

类包

在Java中,我们可以使用class关键字来进行定义一个类,在程序被编译后就会产生一个.class文件。类的定义是规定类名不能重复的,如果程序内只定义了少量的类,那自然不用担心这个问题。
但是,随着类的数量增多,那么难免会出现这个问题,如果根据需求需要定义两个名字相同但是程序逻辑不同的类时,那么该如何解决呢,最好的方法就是将这个两个类放置在不同的包下面。


类的定义规定,在同一个类包下面不允许出来同名的类,但是在不同类包下面就允许出现这种情况,相当于将两个同名的类放入了不同的盒子内,避免出现这个问题。

包和类的关系

类路径
如果一个程序内存在多个同名不同包的max类,那么该如何使用指定包的类呢?
在使用该类时使用该类的类路径,也成为绝对路径。

java.util.Date date=new java.util.Date();        // 选择Java.util包下的Date类
java.sql.Date date2=new java.sql.Date(100)    // 选择Java.sql包下的Date类



 

指定包名(package)
在进行创建包的时候需要注意的是,Java包的命名规则建议使用全小写字母进行命名。
需要了解的是如果一个类没有被定义在一个指定的包内,那么该类就被归纳到默认包(default package)中。


在某个包下面创建一个类的话,需要在这个类的开头加上表达式 package 包名,该表达式需要放置在程序的第一行,使用package关键字指定包名之后,包名也会成为类名的一部分,在不同包下使用该类的话,需要使用 import 包名.类名 的格式。

package test;    //指定包名,表示该类在本包内
public class dome{
}

导包

在Java中,如果需要使用到其它包内的类的话,除了使用该类的绝对路径之外,我们还可以使用Java中 import 关键字来指定。例如,如果在其它包内也定义了一个Math,那么假如我们只想使用该Math类的话,那么我们可以使用import关键字进行导包。

例如:

package test;

import Number_5.Math;   //导包,导入其它包内的Math类

public class Demo_4 {
    public static void main(String[] args) {
        int max = Math.max(4, 6);    // 进行导包后,再使用时,直接使用包名.类名的方法进行使用
        System.out.println(max);
    }
}


在进行导包后,我们在使用该包下的Math类后,可以看到,java.lang包下有一个Java给定的Math类,还有一个我们刚刚进行导的包下的Math类。


需要注意的是,刚刚我们已经导入了Number_5包下的Math类,如果需要使用java.lang包下的Math类的话,需要使用java.lang.Math类的完整路径的方式使用该类。因为如果在之前导入了Number_5包下的Math类的话,程序中如果使用Math类中的方法,编译器只会去Number_5.Math类内进行寻找该方法,如果没有找到则报错。

 

 


如果需要使用java.lang包下的Math类的话,需要使用全名格式,指定编译器去那个包下寻找min方法。

 

需要注意的是,如果使用import导入某个包下的所有类时,这些类并不包括该包下的子包的类。如果需要使用子包中的类时,需要对子包进行单独引用。

import 包名.子包名.*;    //导入所有类
import 包名.子包名.类名;    //导入指定类


导入静态方法或静态成员

使用import关键字还可以对静态方法与静态变量进行导包。

import java.lang.max;
import java.lang.System.out;

public class Demo{
    public static void main(String[] args){
        out.println("较大值为:"+(max(1,4)));    // 导入后可直接使用
    }
}


内部类

内部类顾名思义,就定义在一个类内部的类。

成员内部类
定义在一个类成员位置的内部类,称为成员内部类,在成员内部类中可以使用外部类的的任意成员变量与成员方法,即使该外部类成员变量被private所修饰。

package test;

public class Demo_4 {
    private int num;
    static int i=0;
    
    // 内部类
     class test{
        public void show(){
            // 内部类调用外部类的成员变量
            System.out.println(num);
            System.out.println(i);
        }
    }
}



因为private等权限修饰符是针对外界的调用而进行权限判断的,但是成员内部类定义在该类的内部,那么相对于该类的一部分,就像该类的方法也是可以调用被private修饰的成员变量一般,成员内部类属于外部类的成员之一。

内部类是依赖于外部类的存在而存在。除非程序中已经有了一个外部类的对象,否则内部类一般不会单独存在。


内部类也可以被权限修饰符进行修饰,如果内部类被private修饰,那么外界无法创建内部类的对象,只能在外部类中创建内部类的对象。


该如何获取内部类的对象呢?

两种方法:

对外部类编写get方法,对外提供内部类的对象
如果内部类没有被private修饰,那么可以在外界创建一个内部类的对象;

方法二:直接创建内部类对象

成员内部类创建对象格式:

外部类.内部类 类名 = 外部类对象.new 内部类构造方法();

public class Demo_4{
    public static void main(String[] args) {
        W.N j=new W().new N();    // 链式法创建内部类对象
    }
}

// 外部类
class W {
    // 内部类
     class N {  
    }
}


 

方法一:通过get方法对外提供成员内部类对象
这个方法多用于成员内部类被private修饰时,才使用这个方法。

但是如果成员内部类被private修饰了,那么外界也无法使用成员内部类的变量来接收这个返回值,只能使用多态的方式,让成员内部类的父类进行接收,如果该成员内部类没有继承其它类,那么只能使用Object来接收这个返回值

public class Demo_4{
    public static void main(String[] args) {
        Object a = new W().getN();
    }
}
class W {
    private class N {
    }
    public N getN(){
        return new N();
    }
}


 

外部类与内部类之间也可使用this关键字,如果在内部类中需要使用到外部类的成员变量,那么可以使用外部类.this.变量名的方式使用。

例如:

public class Demo_4{
    public static void main(String[] args) {
        W.N a=new W().new N();
        a.show();
    }
}
class W {
    private int i=10;
    class N {
        private int i=20;
        public void show(){
            int i=30;
            System.out.println(i);          // 方法内的i
            System.out.println(this.i);     // 内部类的i
            System.out.println(W.this.i);   // 外部类的i
        }
    }
}

 

匿名内部类
匿名内部类本质是一个隐藏了名字的内部类。匿名类是只有在创建时才会编写类体的一种写法。

语法格式:

new 继承/实现(){
    //重写的方法
};

匿名内部类在一对大括号 { } 的范围内是一个类,整体却是一个new出来的对象。


例如:

public class Demo_4{
    public static void main(String[] args) {
        // 匿名内部类
        new Swit(){
            @Override
            public void swit(){
                System.out.println("重写了swit方法");
            }
        };
    }
}
interface Swit{
    public void swit();
}



上述匿名内部类处的语法解读。


整体来说就是,使用空参构造创建一个实现了Swit接口的匿名内部类的对象,就是说,创建匿名内部类的地方是创建了一个对象。

匿名内部类编译后会产生一个以 “外部类名$序号“ 为名称的 .class文件,序号以1-n排列,分别代表1-n个匿名内部类。那么我们可以找到这个.class文件,并对其进行反编译来查看我的结论是否正确。


匿名内部类产生的.class文件

javap 命令,可以对.class文件进行反编译,将字节码文件进行反编译,会打印出该字节码文件包含的信息


反编译的结果:被圈起来的是虚拟机自行添加的空参构造与重写的接口方法。


上述反编译的结果可以说明,使用匿名内部类的格式创建的是一个匿名内部类的对象,而大括号内{}的才是匿名内部类的类体。

 


匿名内部类的对象如果没有赋值给任何引用变量的话,该对象会在使用后被Java虚拟机自动销毁。
匿名类不能写构造方法。
匿名类不能定义静态的成员。
那么匿名内部类对象可以赋值给那些引用变量呢?可以被赋值给被继承的接口或者父类对象。形成多态。

父类对象调用子类方法

public class Demo_4{
    public static void main(String[] args) {
        Swit s=new Swit(){
            public void swit(){
                System.out.println("重写了swit方法");
            }
        };
        s.swit();    // 父类对象调用子类重写的方法
    }
}
interface Swit{
    public void swit();
}


 

运行过程

 

匿名内部类的那个整体是一个对象,只有大括号内的才是那个具体的匿名内部类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值