Java中包的作用以及使用、访问权限、单例/多例设计模式、枚举和异常(附带相关面试题)

简介: 本章节讲述以下方面知识点 1.包的作用以及使用 2.单例/多例化设计模式 3.枚举 4.访问权限2.异常

 

目录

1.包的作用以及使用

2.访问权限

2.单例设计模式

3.多例子设计模式

5.枚举 (enum)

6.异常


1.包的作用以及使用

包的本质其实是目录,一个项目如果都在同一个目录下,那么如果项目上有多个人在开发,并且创建的类名是一样的就会产生冲突,并且如果一个项目都在一个包里进行那么也不适合模块化的开发

使用: 包可以通过插入(import)进行使用其他包内的类,但是注意如果调用别的包里的类名字和你自己包里面类名字一样的话,必须要详细的类,即包名加类名

导入方法:import.类  或者import.*(代表自动导入)

举例:我在Example101包和Example102的包中都设置了主类为javaDemo,现在要调用到两个主类

import Example101.*;
import Example101.javaDemo;
import Example102.*;
public class javaDemotest {
    public static void main(String[] args) {
        Example101.javaDemo demo = new javaDemo();
        demo.test1();
        Example102.javaDemo demo1 = new Example102.javaDemo();
        demo1.Test();
    }
}

image.gif

image.gif编辑

静态导入:用static导入则如同放在在主方法上无需进行实例化,如下图可以直接调用想要用的方法

import static java.lang.Math.PI;
import static java.lang.Math.pow;
import static java.lang.System.out;
public class MyClass {
    public static void main(String[] args) {
        // 使用静态导入后,可以直接使用静态成员,无需限定类名
        double radius = 5.0;
        double area = PI * pow(radius, 2);
        out.println("圆的面积:" + area);
    }
}

image.gif

2.系统常用包:

    1. java.lang 包:这是 Java 的核心包,提供了Java语言的基本类和常用工具类。例如,String、Object、System、Math等类就位于该包中。
    2. java.util 包:这个包提供了 Java 中许多实用的工具类,包括集合类(如List、Set、Map等)、日期和时间类、随机数生成器、排序算法等。
    3. java.io 包:这个包提供了进行输入输出操作的类和接口,用于读写文件、网络通信、序列化等操作。例如,File、InputStream、OutputStream、Reader、Writer等都是该包中的常见类。
    4. java.net 包:这个包提供了与网络通信相关的类和接口,用于创建和管理网络连接,进行网络编程等。例如,Socket、URL、URLConnection等类可以用于与服务器进行通信。
    5. java.sql 包:这个包提供了与数据库交互的类和接口,用于执行数据库操作、连接数据库等。例如,Connection、Statement、ResultSet等类可以用于执行 SQL 查询和更新。
    6. java.awt 和 javax.swing 包:这些包提供了 Java 的图形用户界面(GUI)组件和相关类,用于创建图形界面应用程序。例如,Frame、Button、Label等类用于创建窗口和控件。
    7. java.nio 包:这个包提供了新的非阻塞 I/O 进行文件和网络操作。它引入了通道(Channel)和缓冲区(Buffer)的概念,提供更高效和可扩展的 I/O 操作。

    3.jar包

    JAR(Java ARchive)是一种用于打包和分发 Java 类、资源文件和元数据的文件格式。它实际上是一个压缩文件,使用 .jar 扩展名。JAR 包可以包含 Java 类文件(.class)、资源文件(例如图片、配置文件等)和其他相关文件,如清单文件(Manifest)和签名文件。

    功能:

      1. 打包和分发:JAR 包提供了一种方便的方式来打包和分发 Java 应用程序或库。它能够将所有相关文件组织在一个文件中,从而简化了应用程序的部署和发布过程。
      2. 资源管理:JAR 包可以存储和管理各种资源文件,如配置文件、图像、音频和视频等。这些资源文件可以通过类路径直接读取,而不需要指定具体的文件系统路径,方便了资源的访问和使用。
      3. 类加载:JAR 包是 Java 类库和应用程序的重要形式之一。Java 运行时环境(JRE)和开发工具(如编译器、调试器等)可以通过类路径查找和加载 JAR 包中的类和资源,以满足程序的运行需求。
      4. 模块化和依赖管理:JAR 包可以作为模块进行管理,通过定义清单文件(Manifest)中的模块依赖关系,实现模块化的开发和部署。这样可以简化复杂项目的构建和打包过程,并提高代码的可维护性和可扩展性。
      5. 版本控制:JAR 包可以带有版本信息,方便对不同版本的应用程序进行管理和更新。通过使用不同的版本号,可以避免软件升级时的兼容性问题,同时也方便了版本的追踪和回滚。

      jar包的使用:

      jar打包太过于复杂,在以后的maven构建工具中会有讲解一键打包,有兴趣可以了解,本章不做多描述。


      2.访问权限与修饰符

      访问的权限有多个分别是private public default protected

      以下表格展示其四者的对比:

      访问权限 可访问范围
      private 仅类内部可访问
      default 同一包内可访问
      protected 同一包内及子类可访问
      public 所有地方都可以访问,没有限制

      static与final

      static final
      定义 修饰类、方法、变量 修饰类、方法、变量
      作用 静态成员属于类 不可更改的常量或不可继承
      调用方式 类名.静态成员 变量名或类名.常量
      内存分配 在方法区分配内存 在栈上分配内存
      生命周期 随着类的加载而加载 在定义时或运行时被赋值
      修改 可以修改静态成员 不可修改常量的值
      继承 静态成员不被继承 可以被子类继承
      多线程安全 可能存在线程安全问题 不会引起线程安全问题

      面试题:final 在 java 中有什么作用?

      (1)用来修饰一个引用

          如果引用为基本数据类型,则该引用为常量,该值无法修改;

          如果引用为引用数据类型,比如对象、数组,则该对象、数组本身可以修改,但指向该对象或数组的地址的引用不能修改。

          如果引用时类的成员变量,则必须当场赋值,否则编译会报错。

      (2)用来修饰一个方法

      当使用final修饰方法时,这个方法将成为最终方法,无法被子类重写。但是,该方法仍然可以被继承。

      (3)用来修饰类

      当用final修改类时,该类成为最终类,无法被继承。

      比如常用的String类就是最终类。

      面试题:final、finally、finalize 有什么区别?

      final可以修饰类,变量,方法,修饰的类不能被继承,修饰的变量不能重新赋值,修饰的方法不能被重写

      finally用于抛异常,finally代码块内语句无论是否发生异常,都会在执行finally,常用于一些流的关闭。

      finalize方法用于垃圾回收。

      一般情况下不需要我们实现finalize,当对象被回收的时候需要释放一些资源,比如socket链接,在对象初始化时创建,整个生命周期内有效,那么需要实现finalize方法,关闭这个链接。

      但是当调用finalize方法后,并不意味着gc会立即回收该对象,所以有可能真正调用的时候,对象又不需要回收了,然后到了真正要回收的时候,因为之前调用过一次,这次又不会调用了,产生问题。所以,不推荐使用finalize方法。


      3.单例设计模式

      所谓单例,就是指类只能实例化一个对象,比如一个企业的CEO,创建其相应的类后,因为一个公司一般只有一个CEO,所以不能实例化多个,防止其他程序员错误创建。

      如何实现单例的设计模式呢?其实很简单,首先创建一个对象操作过程如下

      Example ex1 = new Example(传参)

      那么就需要在外部(主方法)让其没办法实现这个操作,只需要

      单例设计模式分为两类,饿汉模式懒汉模式

      区分在于其实例化的时机

      1.饿汉模式

      是在类加载的时候就进行实例化,意味着程序一开始就实例化对象

      举例:

      package Example103;
      class CEO{
          private String nn = "就是CEO 就是狂";
          private static final CEO ceoPerson = new CEO();//创建唯一的对象
          private CEO(){} //私有化构造方法让主方法无法构造新的对象
      //    获取私有对象,让主方法能用到唯一的对象
          public static CEO getCeoPerson() {
              return ceoPerson;
          }
          public void getInfo(){
              System.out.println(nn);
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
              CEO me = CEO.getCeoPerson();
              me.getInfo();
          }
      }

      image.gif

      image.gif编辑

      2.懒汉模式

      是指在调用类时候,才开始进行判断是否有唯一一个对象,若没有则创建唯一的对象,与饿汉模式相比,在程序开始时候并不会创建对象,只有要用到的时候才开始创建。其好处是可以减少程序开始运行时候的消耗

      举例:

      package Example104;
      class CEO {
          private String nn = "就是CEO 就是狂";
          private static CEO ceoPerson = null; //只定义对象名,即创建栈名,但是指向NULL
          private CEO() {
          } //私有化构造方法让主方法无法构造新的对象
          //具体如果需要这个岗位才开始创造,否则当作空的
          public static CEO Exist() {
              if (ceoPerson == null) {
                  ceoPerson = new CEO();
              }
              return ceoPerson;
          }
          public static CEO getCeoPerson() {
              return ceoPerson;
          }
          public void getInfo() {
              System.out.println(nn);
          }
      }
      public class javaDemo {
          public static void main(String[] args) {
              CEO.Exist();
              CEO me = CEO.getCeoPerson();
              me.getInfo();
          }
      }

      image.gif

      面试题:Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式

        1. 保证程序只有一个对象的实例,叫做单例模式;
        2. 内部类的方式实现单例模式,是线程安全的;
        3. 双重验证方式实现单例模式也是线程安全的;

        3.多例子设计模式

        刚刚讲述的单例设计模式是指只有一个岗位所以只能实例化一个对象,而多例设计模式就能理解是多个对象,比如红绿灯,只有三个对象,红色,绿色,黄色。其实现过程其实和单例是差不多的。就是将public static final = new 对象1  复制粘贴 成为

        public static final = new 对象1

        public static final = new 对象2

        public static final = new 对象3

        记得私有化构造方法防止其他人创建新的对象

        举例:

        package Example105;
        class trafficLight {
        //创建三个唯一的对象
            private static final trafficLight green = new trafficLight("green");
            private static final trafficLight red = new trafficLight("red");
            private static final trafficLight yellow = new trafficLight("yellow");
            private String color;
        //防止外部调用
            private trafficLight(String color) {
                this.color = color;
            }
            public static trafficLight getGreen() {
                return green;
            }
            public static trafficLight getRed() {
                return red;
            }
            public static trafficLight getYellow() {
                return yellow;
            }
            public void getInfo(trafficLight t) {
                switch (t.color) {
                    case "red":
                        System.out.println("红灯");
                        break;
                    case"green":
                        System.out.println("绿灯");
                        break;
                    case "yellow":
                        System.out.println("黄灯");
                        break;
                }
            }
        }
        public class javaDemo {
            public static void main(String[] args) {
                trafficLight g = trafficLight.getGreen();
                g.getInfo(g);
            }
        }

        image.gif

        image.gif编辑


        5.枚举 (enum)

        枚举类:

        枚举其实就是多例化的设计模式,枚举出有多少个对象,但是枚举也有着很多独特的优势,比如说创造一个红绿灯,三个对象分别是RED GREEN YELLOW 那么可以在其类的内部对其进行switch判断比如说switch(c)case RED 。。。print(“当前为红灯”);一般的对象就没办法直接判断

        如下枚举类的实用举例:

        package Example106;
        enum Color {
            绿色("green"), 红色("red"), 黄色("yellow");//枚举是已经实例化过的对象不需要再在主方法中创建对象
            private String color;
            public void getInfo(Color c){
                switch (c){
                    case 红色:
                        System.out.println("红灯");
                        break;
                    case 绿色:
                        System.out.println("绿灯");
                    case 黄色:
                        System.out.println("黄灯");
                }
            }
        //    构造方法也是如同单例设计模式一样要用私有化防止主方法再创建新的
            private Color(String color){
                this.color = color;
            }
        }
        public class javaDemo {
            public static void main(String[] args) {
                Color red  = Color.红色;
                for (Color c : Color.values()) {
                    System.out.println(c.ordinal()+c.name());
                }
                red.getInfo(red);
            }
        }

        image.gif

        枚举类的实现接口 枚举类实现抽象方法

        image.gif编辑

        只需要多加个接口然后让枚举类去实现(implement)

        枚举类的常用方法:

        方法 描述
        name() 返回枚举常量的名称。
        ordinal() 返回枚举常量在枚举声明中的位置(从 0 开始计数)。
        valueOf(String name) 返回具有指定名称的枚举常量。如果找不到指定名称的枚举常量,将抛出 IllegalArgumentException 异常。
        values() 返回包含所有枚举常量的数组。
        compareTo(E other) 比较枚举常量和指定对象的顺序。如果指定对象为枚举常量,则返回两者在枚举声明中位置的差值;如果指定对象为 null 或不是同一枚举类的实例,则抛出 ClassCastException 异常。
        equals(Object other) 检查枚举常量与指定对象是否相等。
        hashCode() 返回枚举常量的哈希码。
        toString() 返回枚举常量的字符串表示。

        6.异常

        1.一般程序在编辑时候可能不会出现问题,但是运行时候就有可能会出现很多问题,比如说除法 number / number1 ,大家都知道number1 即被除数不能为0 ,但是在写这个的时候可能没有留意也不会弹出异常,但是在运行时候就会出现异常了。一旦产生异常又没有解决措施,那么问题就会给虚拟机jvm处理,jvm就会先打印错误信息后进行中断

        2.异常的关键字 try catch finnally 与方法printStackTrace()

        上面可以知道异常如果不做任何措施的话就会中断,但是很多程序一旦运行就尽量不能终止,否则会给公司带来难以想象的损失,因此就需要用到try catch 与finnally 关键字。先解释以下三者的功能

        try:尝试运行这段代码并查看是否会出现异常,如果尝试的过程出现异常,则立即生成一个对应异常的对象。

        catch:对异常进行判断,因为异常也有很多种类,比如数组可能越界异常,数学计算可能出现异常。还有很多种类异常那么对应的处理也不同,catch就是用来捕捉try产生异常对象的比较,比如catch(ArithmeticException e)表明捕捉数学计算异常,如果匹配成功那么就执行catch内的操作否则跳过。

        finally:不管会不会出现异常都会执行里面的操作

        printStackTrace():打印错误信息与错误在第几行

        举例:

        package Example111;
        class compute {
            int x;
            int y;
            public compute(int x, int y) {
                this.x = x;
                this.y = y;
            }
            public int computeing() {
                System.out.println("开始执行计算");
                try {
                    return x / y;
                } catch (Exception e) {
                    e.printStackTrace();
                    return -1;
                } finally {
                    System.out.println("计算执行结束");
                }
            }
        }
        public class javaDemo {
            public static void main(String[] args) {
                compute c = new compute(1, 2);
                c.computeing();
                compute d = new compute(1, 0);
                d.computeing();
            }
        }

        image.gif

        image.gif编辑

        面试题 :try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗?

        会的

        2.异常的种类

        在 Java 中,异常是以类的形式存在的,它们都是 Throwable 类及其子类的实例。Throwable 是异常类的根类,它有两个直接的子类:Error 和 Exception。

          1. Error:
            • Error 表示程序中的严重问题,通常由虚拟机抛出,并且在大多数情况下不应该被程序员显示捕获。
            • 一旦 Error 被抛出,程序就无法恢复,并终止执行。
            • 常见的 Error 类包括:VirtualMachineError、OutOfMemoryError、StackOverflowError 等。
              1. Exception:
                • 异常是表示非致命性问题或意外情况的类。
                • Exception 又分为两种类型:受检异常(Checked Exception)和非受检异常(Unchecked Exception)。

                  面试题:常见的异常类有哪些?

                    • NullPointerException:空指针异常;
                    • SQLException:数据库相关的异常;
                    • IndexOutOfBoundsException:数组下角标越界异常;
                    • FileNotFoundException:打开文件失败时抛出;
                    • IOException:当发生某种IO异常时抛出;
                    • ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出此异常;
                    • NoSuchMethodException:无法找到某一方法时,抛出;
                    • ArrayStoreException:试图将错误类型的对象存储到一个对象数组时抛出的异常;
                    • NumberFormatException:当试图将字符串转换成数字时,失败了,抛出;
                    • IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数。
                    • ArithmeticException当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。

                    将异常抛给其他人去处理,可能会问有了try catch 明明可以在其类内部就将异常进行处理了,为什么还要进行抛给外面的人去解决呢?其实很好理解,比如在工作时候腿给摔断了,那么应该由谁处理?当然是公司处理,让公司解决你出现的问题。

                    异常抛出关键字 throw

                    package Example112;
                    class test{
                        public test(int number){
                            this.number=number;
                        }
                       int number;
                       public void Eat()throws Exception{
                           System.out.println("吃了"+number+"个包子");
                           if (number>50){
                               throw  new Exception();
                           }
                       }
                    }
                    public class javaDemo {
                        public static void main(String[] args) {
                            test t =new test(99);
                            try {
                                t.Eat();
                            }catch (Exception e){
                            e.printStackTrace();
                            }
                        }
                    }

                    image.gif

                    image.gif编辑

                    面试题  throw 和 throws 的区别?

                    (1)throw

                    作用在方法内,表示抛出具体异常,由方法体内的语句处理;

                    一定抛出了异常;

                    (2)throws

                    作用在方法的声明上,表示抛出异常,由调用者来进行异常处理;

                    可能出现异常,不一定会发生异常;

                    异常的流程:

                    image.gif编辑

                    自定义异常:

                    虽然有很多很多种的异常类但是有很多并不算是正常执行,比如数据过于离谱的这种就应该触发异常。下面我举一个例子,吃包子,一般吃几个包子没问题,但是如果有人输入自己吃的包子过于多了那就不对劲,可以直接触发我们自己定义的异常

                    举例:

                    package Example112;
                    class BaoziException extends Exception {
                        public BaoziException(String message) {
                            super(message);
                        }
                    }
                    class test {
                        int number;
                        public void Eat(int number) throws BaoziException {
                            System.out.println("吃了" + number + "个包子");
                            if (number > 50) {
                                throw new BaoziException("包子数量过多!");
                            }
                        }
                    }
                    public class javaDemo {
                        public static void main(String[] args) {
                            test t = new test();
                            try {
                                t.Eat(60);
                            } catch (BaoziException e) {
                                System.out.println("出现异常:" + e.getMessage());
                            }
                        }
                    }

                    image.gif

                    RuntimeException与Exception区别

                    在 Java 中,异常分为两种类型:RuntimeException 和 Exception。它们之间的区别如下:

                      1. RuntimeException:
                        • RuntimeException 是 Exception 的子类。
                        • RuntimeException 是非受检异常(Unchecked Exception),在编译时不强制要求进行异常处理。
                        • RuntimeException 通常表示程序本身的错误或逻辑错误。
                        • 常见的 RuntimeException 包括:NullPointerException、IllegalArgumentException、ArithmeticException 等。
                          1. Exception:
                            • Exception 是所有异常类的父类,包括 RuntimeException 在内。
                            • Exception 的直接子类中有受检异常(Checked Exception)和非受检异常(Unchecked Exception)。
                            • 受检异常是在编译时强制要求处理的异常。方法必须声明可能抛出的受检异常,并通过 try-catch 块或 throws 子句进行处理,否则程序将无法通过编译。
                            • 非受检异常在编译时不要求强制处理,但仍然可以选择捕获或抛出。
                            • 常见的受检异常包括:IOException、SQLException、ClassNotFoundException 等。

                              区别总结:

                                • RuntimeException 是非受检异常,不需要在编译时强制处理;Exception 中的其他子类都是受检异常,在编译时需要强制处理。
                                • RuntimeException 通常表示程序本身的错误或逻辑错误;Exception 的其他子类通常表示外部资源的故障或不满足某些条件的情况。
                                • 对于 RuntimeException 可以选择捕获或抛出,但不是必需的;对于受检异常,必须进行处理,要么捕获并处理,要么在方法签名中声明 throws 子句。

                                需要注意的是,在设计自定义异常类时,应根据异常的特性和使用场景来决定继承 RuntimeException 还是 Exception。如果异常属于程序的逻辑错误或操作错误,则可以继承 RuntimeException;如果异常属于外部资源故障或需要强制处理的情况,则应继承 Exception 或其子类。

                                目录
                                相关文章
                                |
                                16天前
                                |
                                SQL Java 数据库连接
                                在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
                                在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
                                31 3
                                |
                                19天前
                                |
                                SQL Java 数据库连接
                                打破瓶颈:利用Java连接池技术提升数据库访问效率
                                在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,避免了频繁的连接建立和断开,显著提升了数据库访问效率。常见的连接池库包括HikariCP、C3P0和DBCP,它们提供了丰富的配置选项和强大的功能,帮助优化应用性能。
                                38 2
                                |
                                29天前
                                |
                                Java
                                Java访问外网图片地址时,如何添加代理?
                                【10月更文挑战第14天】Java访问外网图片地址时,如何添加代理?
                                22 2
                                |
                                1月前
                                |
                                小程序 Java
                                小程序访问java后台失败解决方案
                                小程序访问java后台失败解决方案
                                44 2
                                |
                                1月前
                                |
                                小程序 JavaScript Java
                                小程序访问java后台
                                小程序访问java后台
                                27 1
                                |
                                1月前
                                |
                                存储 Java
                                深入理解java对象的访问定位
                                这篇文章深入探讨了Java对象的访问定位机制,比较了使用句柄和直接指针两种主流的对象访问方式,并指出了它们各自的优势,例如句柄访问在对象移动时的稳定性和直接指针访问的速度优势。
                                33 0
                                深入理解java对象的访问定位
                                |
                                2月前
                                |
                                设计模式 存储 安全
                                设计模式——设计模式介绍和单例设计模式
                                饿汉式(静态常量)、饿汉式(静态代码块)、懒汉式(线程不安全)、懒汉式(线程安全,同步方法)、懒汉式(线程不安全,同步代码块)、双重检查(推荐,线程安全、懒加载)、静态内部类(推荐)、枚举(推荐)
                                设计模式——设计模式介绍和单例设计模式
                                |
                                2月前
                                |
                                存储 Java 关系型数据库
                                java: 无法访问org.springframework.context.ConfigurableApplicationContext
                                `亲测可用,之前搜索了很多博客,啥样的都有,就是不介绍报错以及配置用处,根本不懂照抄那些配置是干啥的,稀里糊涂的按照博客搭完也跑不起来,因此记录这个。` `项目背景`:公司项目当前采用http协议+shiro+mysql的登录认证方式,而现在想支持ldap协议认证登录然后能够访问自己公司的项目网站。 `举例说明`:假设我们公司有自己的门户网站,现在我们收购了一家公司,他们数据库采用ldap存储用户数据,那么为了他们账户能登陆我们公司项目所以需要集成,而不是再把他们的账户重新在mysql再创建一遍,万一人家有1W个账户呢,不累死了且也不现实啊。
                                46 11
                                |
                                2月前
                                |
                                安全 Java 编译器
                                java访问字段
                                java访问字段
                                25 6
                                |
                                2月前
                                |
                                安全 Java 编译器
                                java访问类字段
                                java访问类字段