java理论知识笔记一:常见容易混淆的知识点

本文深入探讨了Java中的关键概念,包括循环控制、泛型、hashcode与equals的区别、序列化处理、反射机制等,同时介绍了多线程、I/O流操作及不同I/O模型的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java理论知识笔记一:常见容易混淆的知识点

java基础
1跳出多重循环:

带有标号的的break语句,

 public static  void main(String[] args){
        int[][] array = new int[][]{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}};
        int target = 4;
        Here:
         try {
                boolean falg=true;
                    for(int i=0;i<array.length&&flag ;i++){//通过循环条件控制
                        System.out.println("i" + i );
                        for (int j = 0;j<array[0].length ;j++){
                            if (array[i][j]==target){
                                System.out.println("包含该整数");
                                break Here;
                                flag=false;
                                throw new Exception();//使用try/catch强制跳出循环
                            }
                        }
                    }
                 } catch (Exception e) {

        }
        }
2伪泛型

Java的泛型是伪泛型,这是因为Java在编译期间,所有的泛型信息都会被擦掉,这也就是通常所说类型擦除 。

3hashcode和equals

为什么重写 equals 时必须重写 hashCode 方法?

如果两个对象相等,则 hashcode 一定也是相同的。两个对象相等,对两个对象分别调用 equals 方法都返回 true。但是,两个对象有相同的 hashcode 值,它们也不一定是相等的 。因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。(为了保证效率)

4基本数据类型

Java中的几种基本数据类型是什么?对应的包装类型是什么?各自占用多少字节呢?

Java有8种基本数据类型,分别为:

  1. 6种数字类型 :byte、short、int、long、float、double
  2. 1种字符类型:char
  3. 1种布尔型:boolean。

这八种基本类型都有对应的包装类分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean

基本类型位数字节默认值
int3240
short1620
long6480L
byte810
char162‘u0000’
float3240f
double6480d
boolean1false

对于boolean,官方文档未明确定义,它依赖于 JVM 厂商的具体实现。逻辑上理解是占用 1位,但是实际中会考虑计算机高效存储因素。

注意:

  1. Java 里使用 long 类型的数据一定要在数值后面加上 L,否则将作为整型解析:
  2. char a = 'h'char :单引号,String a = "hello" :双引号

BigDecimal类

《阿里巴巴Java开发手册》中提到:浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。 具体原理和浮点数的编码方式有关。

此时可以使用BigDecimal类实现。

BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");

//加减乘除
a.add(b);
a.subtract(b);
a.multiply(b);
a.divide(b);
//还有转为基本类型的方法
5重写和重载

重写:重写发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。

重载:是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。

6深拷贝和浅拷贝
  1. 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
  2. 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
7Java 序列化中如果有些字段不想进行序列化,怎么办?

对于不想进行序列化的变量,使用 transient 关键字修饰。

transient 关键字的作用是:阻止实例中那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。transient 只能修饰变量,不能修饰类和方法。

public class Apple implements Serializable {

    private static final long serialVersionUID = -1315053955059469208L;
    /**
     * 主键id
     */
    private String id;

    /**
     * 颜色
     */
    private String color;
    //不序列化此字段
    private transient Integer weight;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "id='" + id + '\'' +
                ", color='" + color + '\'' +
                ", weight=" + weight +
                '}';
    }

//    public static boolean isGreenApple(Apple apple) {
//        return "green".equals(apple.getColor());
//    }
//
//    public static boolean isHeavyApple(Apple apple) {
//        return apple.getWeight() > 150;
//    }
}

8.反射机制

(1)Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取t对象的各种信息。

(2)Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

  • 静态编译: 在编译时确定类型,绑定对象
  • 动态编译: 运行时确定类型,绑定对象

反射机制的优缺点:

  • 优点: 运行期类型的判断,动态加载类,提高代码灵活度。

  • 缺点: 1,性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的 java 代码要慢很多。

    ​ 2,安全问题,让我们可以动态操作改变类的属性同时也增加了类的安全隐患。

在运行期间,一个类,只有一个Class对象产生。

反射机制的应用场景:

  1. 我们在使用 JDBC 连接数据库时使用 Class.forName()通过反射加载数据库的驱动程序;
  2. Spring 框架的 IOC(动态加载管理 Bean)创建对象以及 AOP(动态代理)功能都和反射有联系;
  3. 动态配置实例的属性;
9native关键字

调用本地方法。比如本地的c方法。

10 异常

在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 Throwable 类。Throwable: 有两个重要的子类:Exception(异常)Error(错误) ,二者都是 Java 异常处理的重要子类,各自都包含大量子类。

Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java 虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。

Exception(异常):是程序本身可以处理的异常。Exception 类有一个重要的子类 RuntimeException。RuntimeException 异常由 Java 虚拟机抛出。NullPointerException(要访问的变量没有引用任何对象时,抛出该异常)、ArithmeticException(算术运算异常,一个整数除以 0 时,抛出该异常)和 ArrayIndexOutOfBoundsException (下标越界异常)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jcoqdrZO-1607265830312)(D:\file\Java异常类层次结构图.png)]

11java多线程

线程,进程,程序的概念。他们之间的关系?

**程序:**是含有指令和数据的文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态的代码。

**进程:**程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。

**线程:**线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。

线程与进程的不同:

1线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。

2 进程属于操作系统的范畴,主要是同一段时间内,可以同时执行一个以上的程序,而线程则是在同一程序内几乎同时执行一个以上的程序段。

3同类的多个线程共享同一块 内存空间 和一组 系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。

线程的六个基本状态:

(1)NEW 线程构建。但还没有调用start方法

(2)RUNABLE 操作系统的的就绪和运行两种状态。

(3)BLOCKED 阻塞状态。线程阻塞与锁。

(4)WATING 等待状态。需要等待其他线程的通知或中断。

(5)TIME WAITING 超时等待。不同于waitting在指定时间自行返回。

(6)TERMINATED 线程执行完毕

12 IO流

java中的IOL流分类

  • 按照流的流向分,可以分为输入流和输出流;
  • 按照操作单元划分,可以划分为字节流和字符流;
  • 按照流的角色划分为节点流和处理流。

既然有了字节流,为什么还要有字符流?

问题本质想问:不管是文件读写还是网络发送接收,信息的最小存储单元都是字节,那为什么 I/O 流操作要分为字节流操作和字符流操作呢?

回答:字符流是由 Java 虚拟机将字节转换得到的,

问题就出在这个过程还算是非常耗时,

并且,如果我们不知道编码类型就很容易出现乱码问题。

所以, I/O 流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。

如果音频文件、图片等媒体文件用字节流(InputStream,OutputStream)比较好,如果涉及到字符的话使用字符流(Reader, Writer)比较好。

BIO,NIO,AIO 有什么区别?

  • BIO (Blocking I/O): 同步阻塞 I/O 模式,

    数据的读取写入必须阻塞在一个线程内等待其完成。

    在活动连接数不是特别高(小于单机 1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

  • NIO (Non-blocking/New I/O): NIO 是一种同步非阻塞的 I/O 模型,

    在 Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer 等抽象。

    NIO 中的 N 可以理解为 Non-blocking,不单纯是 New。它支持面向缓冲的,基于通道的 I/O 操作方法。 NIO 提供了与传统 BIO 模型中的 SocketServerSocket 相对应的 SocketChannelServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞 I/O 来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发

  • AIO (Asynchronous I/O): AIO 也就是 NIO 2。

    在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的 IO 模型。

    异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步 IO 的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,我们的业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO 操作本身是同步的。查阅网上相关资料,我发现就目前来说 AIO 的应用还不是很广泛,Netty 之前也尝试使用过 AIO,不过又放弃了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值