06Java 类的高级特性篇


Java类包

Java JDK API中提供了类功能,它们封装为类包

类名冲突

JDK API 中提供的类,在同一类包 同类名 会导致编译器无法执行 ,要把类包分开或更改类名

完整的类路径

完整的类名需要包名与类名的组合

java.包名.类名
//例子
java.lang.String

如果指定路径不确定可能会翻车,像以下是需要完整路径
java.util.Date date = new java.util.Date();
java.sql.Date date2 = new java.sql.Date();

java包是为了防止命名冲突,访问控制,提供搜索和定位类、接口、枚举和注释等

没有定义包会自动归纳在预设包(默认包)中,最好为所有类设置包名(良好习惯)

package 包名

注意:

  • 在类中指定包名时,需要将 package 表达式 放在程序的第一行,必须是,非注释代码

  • Java包的命名规则是全部使用小写字母的

import 关键字导入包

引入包可以调用包中的方法,不能调用两包中的同类名,指定包后面有 * ,代表使用包中的所有类

默认包中的类

import noa.out;

public class Demo {
    public static void main(String[] args) {
        out a = new out();
        a.show();

        nob.out2 b = new nob.out2();
        b.show();
    }
}

noa包 中的 out类

package noa;

public class out {

    public void show(){
        System.out.println("测试1"); }

}

nob包 中的 out2类

package nob;

public class out2 {

        public void show(){
            System.out.println("测试2"); }
}

运行结果

测试1
测试2

import 关键字导入静态成员

import static 静态成员

例子:

java.lang.System 类中的out成员变量
java.lang.Math 类中的max成员方法

它们都是静态成员,这是前提!!!

import static java.lang.System.out; //导入静态成员方法
import static java.lang.Math.max;   //导入静态成员变量

public class Demo2 {
    public static void main(String[] args) {
        //静态成员简写调用
        out.println("123");
        System.out.println("123");
        //静态方法简写调用
        out.println("max(3,4)?"+max(3,4));
        out.println("max(3,4)?"+Math.max(3,4));
    }
}

运行结果

123
123
max(3,4)?4
max(3,4)?4

final关键字

final变量

final 声明的变量,设定后,不能更改该变量的值,被final设置的变量称为常量!!

final 数据类型 变量名 =;

final方法

final 定义的方法,不能被其他子类重写该方法

用private修饰符(限于本类使用)修饰的方法隐式被指定为 final类型 ,可不需再定义 final 类型

[修饰符] final 数据类型 方法名([参数]){···} 

final类

final 定义的类,不能被继承 (跟部分API类类似)

final class 类名{···}

final定义

变量 不能被更改

方法 不能被重写

类 不能被继承

例子

public class Demo {
    //final变量   常量IP
    final double IP = 3.14;
    public static void main(String[] args) {

//        IP = 3.143;不能赋值更改

        no1 n = new no1();
        n.show();
//        n.show2();不能访问

        no2 n2 = new no2();
        n.show();//调用继承父类的方法
//        n.show2();不能访问

    }
}

class no1{
    //show() final方法
    public final void show(){
        System.out.println("测试1");
    }

    private void show2(){
        System.out.println("测试2");
    }

}

//no3 final类
final class no2 extends no1{
    /*
    不能重写 父类show()方法
    public void show(){
        System.out.println("测试1");
    }
    */
    private final void show2(){
        System.out.println("测试2");
    }
}

//class no3 extends no2{····}不能继承

运行结果

测试1
测试1

内部类

一个类中再定义一个类,在类中再定义的类 称为内部类

成员内部类

可直接使用所在的类中的成员方法 / 成员变量

注意:

  • 在外部类外和非静态方法外实例内部类对象,需要外部类指定该对象的类型
  • 访问 被 private修饰的内部类方法,需要接口重写调用
  • this关键字调用本类的成员变量,外类需要类名作为前缀。如果多类需要完整的类路径

1.内部类调用外部类变量和方法及 private修饰 的访问

public class Demo {
    public int i = 123;
    private int j = 345;
    class Demoo{

//        int i = 456;
        public void show(){
            //共用外类的变量
            System.out.println("调用内部类(Demo2)的show()方法输出i , j:"+i+"、"+j);
        }
        public void ssc(){
            System.out.println("在内部类调用外类ss()方法");
            //调用外类的ss()方法
            Demo.this.ss();

            System.out.println("\n在内部类调用外类sss()方法");
            //调用外类的sss()方法
            Demo.this.sss();
        }

    }

    public void show(){
        System.out.println("调用Demo类的show()方法输出i , j:"+i+"、"+j);
    }

    //public 修饰的外部类方法
    public void ss(){
        System.out.println("调用sss()方法,public修饰");
    }

    //private 修饰的外部类方法
    private void sss(){
        System.out.println("调用ss()方法,private修饰");
    }

    //在外部类实例化内部类对象引用
    Demoo n3 = new Demoo();

    public static void main(String[] args) {
        System.out.println("内部类的变量使用以及比较:");
        Demo n = new Demo();
        n.show();
//        Demo2 n2 = new Demo2(); 无法引用
        Demo.Demoo n2 = n.new Demoo();
        n2.show();
        System.out.println("\n内部类的方法调用:");
        n2.ssc();

    }
}

运行结果

内部类的变量使用以及比较:
调用Demo类的show()方法输出i , j:123、345
调用内部类(Demo2)的show()方法输出i , j:123、345

内部类的方法调用:
在内部类调用外类ss()方法
调用sss()方法,public修饰

在内部类调用外类sss()方法
调用ss()方法,private修饰

2.private修饰的内部类向上转型为接口

能隐藏内部类方法运行情况,但仅限于接口抽象方法重写的访问

interface nn{
    void f();
}

public class Demo2 {
    public static void main(String[] args) {
        System.out.println("no1类使用隐藏内部类的方法:");
        no1 cc = new no1();
        //通过no1类doit()方法返回 nn接口
        nn cc2 = cc.doit("Java");
        cc2.f();
//        cc2.f2();仅限于接口抽象方法的访问
    }
}

class no1{
    //隐式内部类
    private class no2 implements nn{
        //内部类的构造方法
        no2(String s){
            System.out.println("隐藏内部类获取的字符串:"+s);
        }

        //重写接口方法
        @Override
        public void f() {
            System.out.println("调用隐藏内部类接口f()方法");
        }

        public void f2(){
            System.out.println("测试内部类的方法的访问");
        }

    }
    //返回接口 ,实例化内部类
    public nn doit(String str){
        return new no2(str);
    }
}

运行结果

no1类使用隐藏内部类的方法:
隐藏内部类获取的字符串:Java
调用隐藏内部类接口f()方法

3.使用 this 获取内部类与外部类的引用

interface D3nn {
    public void out(int i);
}

public class Demo3{

    private int i = 88;
    private class Demoo3 implements D3nn{
        private int i = 99;
        @Override
        public void out(int i){
            System.out.println("参数i:"+i);
            System.out.println("内部类i:"+this.i);
            System.out.println("外部类i:"+Demo3.this.i);
        }
    }
    public D3nn doit(){
        return new Demoo3();
    }
}

class diao{
    public static void main(String[] args) {
        //实例化外部类
        Demo3 n = new Demo3();
        //通过外部类doit()方法获取接口调用内部类重写方法
        D3nn n2 = n.doit();
        n2.out(66);
    }
}

运行结果

参数i:66
内部类i:99
外部类i:88

局部内部类

类定义在方法或任意的作用域中均可定义为内部类

方法不能访问内部类,但内部类可以访问当前方法的常量以及所有成员

//定义接口
interface D4nn{ }

public class Demo4 {

    //doit方法返回接口调用
    public D4nn doit(String s){

        class Demoo4 implements D4nn{
            //内部类的构造方法
            public Demoo4(String x) {
                //外部类方法参数覆盖内容
                x = s;
                //内部类获取的参数
                System.out.println(x);
            }

        }
        //返回内部类对象
        return new Demoo4("参数测试22");
    }

    //主方法调用方法
    public static void main(String[] args) {
        Demo4 n = new Demo4();
        n.doit("参数测试11");
    }

}

运行结果

参数测试11

匿名内部类

匿名内部类没有名称,默认使用构造方法接口对象,匿名定义结束要有分号标识

//定义接口
interface D5nn{
    public void Demoo5(String x);
}

public class Demo5 {

    public D5nn doit(String s){
        return new D5nn(){
            //内部类的构造方法
            @Override
            public void Demoo5(String x) {
                //外部类方法参数覆盖内容
                x = s;
                //内部类获取的参数
                System.out.println(x);
            }
        };
    }

    public static void main(String[] args) {
        Demo5 n = new Demo5();
        D5nn  n2 = n.doit("参数匿名类");
        n2.Demoo5("参数匿名类2");
    }

}

运行结果

参数匿名类

静态内部类

内部类前面加static关键字即可,变成静态内部类,静态内部类只能调用静态的成员,用于调试

  • 如果创建静态内部类对象,不需要外部类的对象
  • 不能从静态内部类的对象中访问非静态外部类的对象
//静态内部类

public class Demo6 {
    int i = 11;
    static int i2 = 22;

    static class Demoo6 {
        public Demoo6(){
//            System.out.println(i);无法打印i ,i非静态
            System.out.println(i2);
        }

        //内部类里写主方法 !! 用于测试内部类
        public static void main(String[] args) {
            Demoo6 n = new Demoo6();
        }

    }

}

运行结果

22

内部类继承

内部类继承相对较复杂,需要设置专门的语法完成

继承内部类时,必须有构造方法带参数的,参数是内部类的外部类对象,同时构造方法里有使用 a.super() 语句

public class Demo7 {

    //内部类
    public class Demoo7{

        public void gg(){ }

    }

    public static void main(String[] args) {
        cs n = new cs(new Demo7());
        n.gg();
    }

}

//cs 继承 Demoo7内部类
class cs extends Demo7.Demoo7{
    //构造方法的参数是外部类的对象
    public cs(Demo7 d){
        d.super();
    }

    @Override
    public void gg() {
        System.out.println("测试");
    }

}

运行结果

测试

文章作者: 柏竹
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 柏竹 !
评论
  目录