Java基础知识面试题

news2024/11/24 2:36:41

Java概述

何为编程

编程就是使用某种程序设计语言编写程序代码让计算机解决某个问题

为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的过程就是编程。

什么是Java

Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程 。

jdk1.5之后的三大版本

1、Java SE(J2SE,Java 2 Platform Standard Edition,标准版)

Java SE 以前称为 J2SE。它允许开发和部署在桌面、服务器、嵌入式环境和实时环境中使用的 Java 应用程序。Java SE 包含了支持 Java Web 服务开发的类,并为Java EE和Java ME提供基础。

2、Java EE(J2EE,Java 2 Platform Enterprise Edition,企业版)

Java EE 以前称为 J2EE。企业版本帮助开发和部署可移植、健壮、可伸缩且安全的服务器端Java 应用程序。Java EE 是在 Java SE 的基础上构建的,它提供 Web 服务、组件模型、管理和通信 API,可以用来实现企业级的面向服务体系结构(service-oriented architecture,SOA)和 Web2.0应用程序。2018年2月,Eclipse 宣布正式将 JavaEE 更名为 JakartaEE

3、Java ME(J2ME,Java 2 Platform Micro Edition,微型版)

Java ME 以前称为 J2ME。Java ME 为在移动设备和嵌入式设备(比如手机、PDA、电视机顶盒和打印机)上运行的应用程序提供一个健壮且灵活的环境。Java ME 包括灵活的用户界面、健壮的安全模型、许多内置的网络协议以及对可以动态下载的连网和离线应用程序的丰富支持。基于 Java ME 规范的应用程序只需编写一次,就可以用于许多设备,而且可以利用每个设备的本机功能。

JVM、JRE和JDK的关系

1、JVM

Java Virtual Machine是Java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。

2、JRE

Java Runtime Environment包括Java虚拟机和Java程序所需的核心类库等。核心类库主要是java.lang包:包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等

3、JDK

Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。所以安装了JDK, 就无需再单独安装JRE了。其中的开发工具:编译工具(javac.exe),打包工具(jar.exe)等

什么是跨平台性?原理是什么

跨平台性是指软件能够在不同的操作系统和硬件平台上运行的能力。

Java具有跨平台性是因为Java字节码可以在不同的操作系统和硬件平台上运行,而不需要对字节码进行修改,这是Java虚拟机(JVM)的工作。

Java的跨平台原理是基于Java虚拟机(JVM)的。Java编译器将Java源代码编译成Java字节码,然后Java虚拟机(JVM)将这些字节码加载到内存中,并在运行时解释执行这些字节码。由于Java虚拟机(JVM)是与平台无关的,因此Java程序可以在不同的操作系统和硬件平台上运行。

Java语言有哪些特点

  • 简单易学(Java语言的语法与C语言和C++语言很接近)
  • 面向对象(封装,继承,多态)
  • 平台无关性(Java虚拟机实现平台无关性)
  • 支持网络编程并且很方便(Java语言诞生本身就是为简化网络编程设计的)
  • 支持多线程(多线程机制使应用程序在同一时间并行执行多项任务)
  • 健壮性(Java语言的强类型机制、异常处理、垃圾的自动收集等)

什么是字节码?采用字节码的最大好处是什么

1、字节码

Java源代码经过编译器(例如IDEA软件)编译后产生的文件(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。

2、采用字节码的好处

采用字节码的好处主要有以下几点:

1. 跨平台性:Java字节码是一种中间语言,可以在不同的操作系统和硬件平台上运行,这使得Java具有跨平台性。

2. 安全性:Java字节码可以在运行时进行安全检查,防止程序对系统造成损害。

3. 高效性:Java字节码可以通过即时编译器(JIT)在运行时进行优化,提高程序的执行效率。

4. 反编译困难:Java字节码是一种二进制文件,相对于源代码来说更难以被反编译,这有助于保护程序的知识产权。

5. 动态性:Java字节码可以在运行时动态生成和加载,这使得Java具有更强的动态性和灵活性。

总之,采用字节码是Java语言的一大特色,也是Java成为一种广泛应用的编程语言的重要原因之一。

3、编译与解释并存

Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做字节码(即扩展为.class的文件),它不面向任何特定的处理器,只面向虚拟机。Java源程序经过虚拟机编译器编译后变成字节码,字节码由虚拟机解释器执行,解释器将其翻译成特定机器上的机器码,然后在特定的机器上运行,这就是上面提到的Java的特点的编译与解释并存的解释。

流程:Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm把字节码发给解释器----->解释器将其翻译成特定机器上的机器码------>程序运行。

补充:不同操作系统的jvm虚拟机是一样的吗?

不同操作系统的JVM虚拟机是不一样的。尽管Java虚拟机规范定义了Java虚拟机的行为和接口,但是Java虚拟机的实现是与操作系统相关的,因为Java虚拟机必须与操作系统交互来实现Java程序的执行。

不同操作系统的JVM虚拟机在实现上可能存在一些差异,比如内存管理、线程调度、垃圾回收等方面的实现会因为操作系统的不同而有所不同。此外,JVM虚拟机还需要与操作系统交互来实现一些底层功能,比如文件操作、网络通信等,这些功能的实现也会因为操作系统的不同而有所不同。

尽管不同操作系统的JVM虚拟机存在一些差异,但是它们都遵循Java虚拟机规范,保证了Java程序在不同操作系统上的可移植性和跨平台性。

什么是Java程序的主类?

Java 应用程序是由若干类和接口组成的,为了使Java 应用程序能够运行,至少要有一个类含有main()主方法,因为main()主方法是Java 应用程序的入口点,Java 应用程序就是从这里开始运行的,我们把含有main()主方法的类称为Java 应用程序的主类。

骚戴理解:很容易误认为有public的类就是主类,注意有public的类不一定是主类。在Java程序中,可以有多个public类,但是只能有一个主类(Main Class),主类是程序的入口点,是Java虚拟机启动程序时调用的类。

在Java程序中,主类必须包含一个public static void main(String[] args)方法,这个方法是程序的入口点,Java虚拟机会从这个方法开始执行程序。因此,只有包含这个方法的类才能作为主类。

如果有多个public类都包含了main方法,那么只有其中一个类可以作为主类,其他类只能作为辅助类。如果没有public类包含main方法,那么程序将无法运行。

Java 应用程序是从main()主方法开始运行的,在Java 应用程序中将含有main()主方法的类称为主类,而在一个Java 应用程序中,开发人员往往为了测试的方便,会为每个类添加一个主方法,但是在测试完以后,应该记着将进行测试的主方法删除,只保留主类中唯一的一个主方法。

Java和C++的区别

Java和C++是两种不同的编程语言,它们之间存在以下几点区别:

1. 语言类型:Java是一种面向对象的编程语言,而C++既可以面向过程编程,也可以面向对象编程。

2. 平台依赖性:Java具有很好的跨平台性,可以在不同的操作系统和硬件平台上运行,而C++的程序在不同的操作系统上需要重新编译。

3. 内存管理:Java具有自动内存管理机制,程序员不需要手动管理内存,而C++需要程序员手动进行内存管理。

4. 异常处理:Java中的异常处理机制比C++更加完善和规范。

5. 安全性:Java具有更好的安全性,可以防止程序对系统造成损害,而C++程序可以访问系统的底层资源,存在一定的安全风险。

6. 开发效率:Java的开发效率比C++更高,Java具有更丰富的类库和工具,可以快速开发出高质量的应用程序。

总之,Java和C++是两种不同的编程语言,它们各有优缺点,适用于不同的场景和需求。Java适合于开发跨平台的应用程序和Web应用,而C++适合于开发需要高性能和底层控制的应用程序,如操作系统、驱动程序等。

基础语法

Java有哪些数据类型

定义:Java语言是强类型语言,对于每一种数据都定义了明确的具体的数据类型,在内存中分配了不同大小的内存空间。

Java的引用数据类型包括以下几种:

1. 类类型(Class Type):类类型是指由类定义的数据类型,包括自定义类和Java API中的类。

2. 接口类型(Interface Type):接口类型是指由接口定义的数据类型,接口定义了一组方法的签名,而不包含方法的实现。

3. 数组类型(Array Type):数组类型是指由相同数据类型的元素组成的有序集合,可以通过下标来访问每个元素。

4. 枚举类型(Enumeration Type):枚举类型是指由一组具名常量组成的数据类型,每个常量都有一个唯一的名称和一个预定义的值。

5. 注解类型(Annotation Type):注解类型是指由注解定义的数据类型,注解用于为程序元素添加元数据。

除了以上几种引用数据类型,Java还有一种特殊的引用类型——null类型,它表示一个空引用。当一个引用变量没有指向任何对象时,它的值为null。

8种java基本数据类型的详细解释

8种java基本数据类型的详细解释

在JDK8的官方文档中,boolean类型仍然占用1个字节(8位)。Java中的boolean类型只有两个取值:true和false,因此只需要1个字节的存储空间就可以表示它们。在JDK8中,boolean类型的范围仍然是true和false,没有发生变化,因此它的存储空间也没有发生变化。

骚戴理解:char占两个字节,在Java中,String类型是一个引用类型,它表示一个字符串对象。String对象占用的字节数取决于字符串的长度和编码方式。

在Java中,字符串默认使用UTF-16编码,每个字符占用2个字节。因此,如果一个字符串包含n个字符,则它占用的字节数为2n个字节。例如,字符串"Hello World"包含11个字符,因此它占用的字节数为22个字节。

需要注意的是,字符串对象本身也需要一定的存储空间,包括对象头和其他元数据。在32位Java虚拟机中,一个空的String对象占用16个字节,在64位Java虚拟机中,一个空的String对象占用24个字节。因此,实际上一个字符串对象占用的总字节数为2n加上对象头和其他元数据的字节数。

switch 是否能作用在 byte 上?是否能作用在 long 上?是否能作用在 String 上?

在Java中,switch语句可以作用在byte、short、char、int、枚举类型和String类型上,但不能作用在long类型上。

具体来说:

1. byte、short、char、int和枚举类型:这些类型可以作为switch语句的表达式类型,因为它们的取值范围是有限的,可以作为case语句的常量表达式。

2. long类型:由于long类型的取值范围较大,无法枚举所有的取值,因此不能作为switch语句的表达式类型。

3. String类型:从Java SE 7开始,String类型也可以作为switch语句的表达式类型。在使用String类型作为表达式时,case语句后面跟的是字符串常量,而不是整数常量。

需要注意的是,无论是哪种类型,case语句后面的值必须是常量表达式,不能是变量或者其他表达式。

用最有效率的方法计算 2 乘以 8

计算2乘以8,最有效率的方法是使用位运算。因为位运算比乘法运算和除法运算更快。

具体来说,可以使用左移运算符(<<)实现2乘以8的计算。左移运算符将一个二进制数向左移动指定的位数,相当于将这个数乘以2的指定次幂。

对于2乘以8,可以将2左移3位,即2 << 3,得到的结果为16。因此,最有效率的方法计算2乘以8的结果为16。

Math.round(11.5) 等于多少?Math.round(-11.5)等于多少

Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。Math.round是取大于这个数的最小整数

骚戴理解:通俗易懂的讲就是四舍五入

float f=3.4;是否正确

不正确!3.4 是双精度数,将双精度型(double)赋值给浮点型(float)属于下转型(down-casting,也称为窄化) 会造成精度损失,因此需要强制类型转换float f =(float)3.4; 或者写成 float f =3.4F; 

short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 += 1;有错吗

对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int型,需要强制转换类型才能赋值给short 型。

而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 = (short(s1 + 1);其中有隐含的强制类型转换。

Java语言采用何种编码方案?有何特点?

Java语言采用Unicode字符集来表示字符和字符串,Unicode字符集是一种全球通用的字符编码方案,它包含了世界上几乎所有的字符,包括各种语言的字母、数字、符号、汉字等。Java中的char类型和String类型都使用Unicode字符集来表示。

在Java中,Unicode字符集采用UTF-16编码方式进行存储,每个字符占用2个字节。UTF-16编码方式是一种可变长的编码方式,在表示ASCII字符时只需要一个字节,而在表示非ASCII字符时需要两个字节或者四个字节。UTF-16编码方式可以保证所有的Unicode字符都能被正确地表示,并且支持快速的随机访问和长度计算。

Java中的字符串常量也采用Unicode字符集和UTF-16编码方式进行存储。在Java源代码中,可以直接使用Unicode转义序列来表示任意的Unicode字符,例如"\u4e2d\u6587"表示中文。Java编译器会将这些转义序列转换为对应的Unicode字符,然后存储到class文件中。在程序运行时,Java虚拟机会将这些Unicode字符转换为UTF-16编码方式,并存储到内存中。

Java注释

1、Java注释的定义

定义:用于解释说明程序的文字分类

2、Java注释的分类

单行注释格式: // 注释文字

多行注释格式: /* 注释文字 */

文档注释格式:/** 注释文字 */

3、Java注释的作用

在程序中,尤其是复杂的程序中,适当地加入注释可以增加程序的可读性,有利于程序的修改、调试和交流。注释的内容在程序编译的时候会被忽视,不会产生目标代码,注释的部分不会对程序的执行结果产生任何影响。多行和文档注释都不能嵌套使用。

访问修饰符

1、访问修饰符定义

Java中,可以使用访问修饰符来保护对类、变量、方法和构造方法的访问。Java 支持 4 种不同的访问权限。

2、访问修饰符分类

private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)

default (即缺省,什么也不写,不使用任何关键字): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。

protected : 对同一包内的类和不同包的所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。

public : 对所有类可见。使用对象:类、接口、变量、方法

3、访问修饰符图

&和&&的区别

&和&&的区别

&和&&都是Java中的逻辑运算符,用于判断两个布尔表达式的逻辑关系。它们的区别如下:

1. &是逻辑与运算符,它的两个操作数都会被求值,只有当两个操作数都为true时,结果才为true。即使第一个操作数为false,第二个操作数也会被求值。

2. &&也是逻辑与运算符,它的两个操作数都会被求值,但是当第一个操作数为false时,第二个操作数不会被求值,直接返回false。只有当第一个操作数为true时,才会继续求值第二个操作数。

因此,&&运算符具有短路求值的特点,可以避免不必要的计算,提高程序的效率。在实际开发中,如果两个操作数都是常量或者字面量,建议使用&&运算符,可以避免不必要的计算。

需要注意的是,&和&&的优先级不同,&&的优先级比&高。在使用时,应该根据实际需要加上括号,以避免优先级问题导致的错误。

Java 有没有 goto

Java中没有goto语句,这是由Java语言设计者故意决定的。goto语句是一种无限制的跳转语句,它可以跳转到程序中的任何一行代码,包括循环、条件语句等。goto语句虽然可以简化程序的编写,但是会使程序结构变得混乱和难以理解,容易引起逻辑错误和调试困难。

为了避免goto语句的缺陷,Java语言设计者采用了其他的控制结构来代替goto语句,比如循环语句、条件语句、异常处理语句等。这些控制结构可以更加清晰地表达程序的逻辑结构,使程序更容易理解和维护。

需要注意的是,Java中有一个标签(Label)语句,可以用于给代码块起一个名字,但是它不能像goto语句一样随意跳转到任何一行代码,只能用于在嵌套的循环语句或者switch语句中跳出多层循环或者switch语句。在实际开发中,应该避免使用标签语句,以保持程序的简洁和清晰。

在Java中,没有goto语句,也不推荐使用。但是可以使用标签(Label)语句来跳出多层循环。下面是一个使用标签语句来跳出多层循环的示例代码:

outer:
for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (i * j > 50) {
            System.out.println("i=" + i + ", j=" + j);
            break outer;
        }
    }
}

在这个示例代码中,使用了一个outer标签来标识外层循环。当内层循环中的条件满足时,使用break outer语句来跳出外层循环,从而实现了跳出多层循环的效果。

需要注意的是,使用标签语句来跳出多层循环虽然可以实现跳转的效果,但是会使程序结构变得复杂和难以理解,容易引起逻辑错误和调试困难。在实际开发中,应该尽量避免使用标签语句,以保持程序的简洁和清晰。

final 有什么用?

用于修饰类、属性和方法;

  1. 被final修饰的类不可以被继承
  2. 被final修饰的方法不可以被重写
  3. 被final修饰的变量不可以被改变

final finally finalize区别

final、finally和finalize是Java中三个不同的关键字,它们的作用和用法各不相同。它们的区别如下:

1. final关键字用于修饰类、方法和变量,表示它们是不可变的。final修饰的类不能被继承,final修饰的方法不能被重写,final修饰的变量不能被重新赋值。final关键字可以提高程序的性能和安全性,避免意外的修改。

2. finally关键字用于定义一个代码块,无论try语句块中是否发生异常,finally语句块中的代码总是会被执行。finally语句块通常用于释放资源、关闭文件、清理数据等操作,保证程序的健壮性和可靠性。

3. finalize方法是Object类中的一个方法,用于在垃圾回收器回收对象之前执行一些清理操作。finalize方法在对象被垃圾回收之前被调用,可以用于释放资源、关闭文件等操作,但是不建议这么做。但是finalize方法不是Java中的析构函数,不能保证一定被调用,也不能保证在对象被回收之前立即执行。

finalize方法是Java中的垃圾回收机制的一部分,它在垃圾回收器回收对象之前被调用,但是不能保证在对象被回收之前立即执行。这是因为Java的垃圾回收机制是异步的,垃圾回收器并不会立即回收对象,而是在一定的时间间隔后才会启动垃圾回收器进行回收。因此,finalize方法的执行时间是不确定的,可能会被延迟到下一次垃圾回收时才被执行。

另外,由于finalize方法的执行时间不确定,因此不能在finalize方法中进行重要的操作,比如释放系统资源、关闭文件等操作。如果在finalize方法中进行这些操作,可能会导致系统资源泄漏、文件无法关闭等问题。

因此,建议在Java程序中尽量避免使用finalize方法,而是采用其他方式来释放系统资源和清理数据,比如使用try-with-resources语句块来自动关闭文件等资源。

需要注意的是,final、finally和finalize虽然名称相似,但是它们的作用和用法是完全不同的,不要混淆使用。

this关键字的用法

this是自身的一个对象,代表当前对象本身

this的用法在java中大体可以分为3种:

1、普通的直接引用,this相当于是指向当前对象本身。

2、在构造方法里形参与成员名字重名,用this来区分:

publicPerson(String name,int age){

this.name = name;

this.age = age;

}

3、引用本类的构造函数

classPerson{

private String name;

private int age;

public Person(){}

public Person(String name){

this.name = name;

}

public Person(String name,int age){

this(name);

this.age = age;

}

}

this(参数):调用本类中另一种形式的构造函数(应该为构造函数中的第一条语句)。

super关键字的用法

super相当于是指向当前对象的父类的引用

super也有三种用法:

1.普通的直接引用

与this类似,super相当于是指向当前对象父类的引用,这样就可以用super.xxx来引用父类的成员。

2.子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分

class Person{

    protected String name;

    public Person(String name){

        this.name = name;

    }

}

class Student extends Person{

    private String name;

    public Student(String name, String name1){

        super(name);

    this.name = name1;

}

publicvoidgetInfo(){

    System.out.println(this.name);//Child
    
    System.out.println(super.name);//Father

    }

}

publicclassTest{

public static void main(String[] args){
    
    Student s1=newStudent("Father","Child");

    s1.getInfo();

    }

}

3、引用父类构造函数

super(参数):调用父类中的某一个构造函数(应该为构造函数中的第一条语句)。

this与super的异同

super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)

this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)

1、super()和this()的区别

  • this关键字用于引用当前对象,可以用于访问当前对象的成员变量和成员方法。this关键字还可以用于调用当前类的其他构造方法,以实现构造方法的重载。

  • super关键字用于引用父类对象,可以用于访问父类的成员变量和成员方法。super关键字还可以用于调用父类的构造方法,以实现子类的构造方法。

  • this关键字可以省略,Java编译器会自动判断当前对象是否需要使用this关键字。而super关键字不能省略,必须显式地指定父类的构造方法。

2、super()和this()的相同点

  • super()和this()均需放在构造方法内第一行。
  • this和super都必须在构造方法或者实例方法中使用,不能在static环境中使用。包括:static变量,static方法,static语句块。
  • this和super都可以用于访问对象的成员变量、成员方法和构造方法

3、注意事项

this和super不能同时出现在一个构造函数里面,是因为它们都是用于调用构造方法的关键字,使用它们会引起歧义。在Java中,构造函数的第一行必须是调用本类或父类的构造方法,如果同时使用this和super,编译器无法确定应该调用哪一个构造方法,会导致编译错误。

static存在的主要意义

static是Java中的一个关键字,它可以用于修饰变量、方法和代码块。static存在的主要意义如下:

1. 共享内存空间。使用static修饰的变量和方法都属于类的静态成员,它们只会在内存中存在一份,被所有的对象共享。这样可以节省内存空间,避免重复创建对象和数据冗余。

2. 方便访问。使用static修饰的变量和方法可以通过类名直接访问,不需要先创建对象。这样可以方便地访问类的静态成员,避免了创建对象的麻烦。

3. 实现工具类和单例模式。使用static修饰的方法可以实现工具类和单例模式。工具类中的方法通常不需要创建对象,可以直接调用,而单例模式中的对象只需要创建一次,可以使用静态变量和静态方法来实现。

4. 初始化顺序。使用static修饰的代码块和变量会在类加载时被初始化,可以用于控制初始化顺序和实现一些复杂的初始化操作。

需要注意的是,static虽然具有很多优点,但是也有一些缺点。使用static会增加代码的耦合性和复杂性,可能会导致线程安全问题和内存泄漏问题。因此,在使用static时需要谨慎考虑,避免滥用。

1、为什么说static块可以用来优化程序性能?

static块可以用来优化程序性能的原因是因为它可以在类被加载时执行,而不需要等到类被实例化时才执行。这样可以避免在类被实例化时重复执行一些初始化操作,从而提高程序的性能。因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。

补充:static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。

2、static的独特之处

1、被static修饰的变量或者方法是独立于该类的任何对象,也就是说,这些变量和方法不属于任何一个实例对象,而是被类的实例对象所共享。

2、在该类被第一次加载的时候,就会去加载被static修饰的部分,而且只在类第一次使用时加载并进行初始化,注意这是第一次用就要初始化,后面根据需要是可以再次赋值的。

3、static变量值在类加载的时候分配空间,以后创建类对象的时候不会重新分配。赋值的话,是可以任意赋值的!

4、被static修饰的变量或者方法是优先于对象存在的,也就是说当一个类加载完毕之后,即便没有创建对象,也可以去访问。

3、static应用场景

1. 静态成员。使用static修饰的变量、方法和代码块都属于类的静态成员,它们只会在内存中存在一份,被所有的对象共享。这样可以节省内存空间,避免重复创建对象和数据冗余。

2. 静态方法。使用static修饰的方法可以直接通过类名调用,不需要先创建对象。静态方法不依赖于任何对象,可以被多个对象共享,因此可以用于实现工具类和单例模式。

3. 静态代码块。使用static修饰的代码块会在类被加载时执行,可以用于实现一些复杂的初始化操作,避免在类被实例化时重复执行一些初始化操作。

4. 静态内部类。使用static修饰的内部类属于类的静态成员,可以直接通过类名访问。静态内部类不依赖于外部类的实例,可以独立存在,因此可以用于实现一些工具类和辅助类。

4、static注意事项

1、静态只能访问静态。

2、非静态既可以访问非静态的,也可以访问静态的。

break ,continue ,return 的区别及作用

return

return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。 一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。

public class ReturnTest
{
  public static void main(String[] args){
    // 一个简单的for循环
    for (int i = 0; i < 3 ; i++ ){
      System.out.println("i的值是" + i);
      if (i == 1){
        return;
      }
      System.out.println("return后的输出语句");
    }
  }
}

continue

continue的功能和break有点类似,区别是continue只是中止本次循环,接着开始下一次循环。而break则是完全中止循环。

public class ContinueTest
{
  public static void main(String[] args){
// 一个简单的for循环
    for (int i = 0; i < 3 ; i++ ){
        for (int j = 0; j < 3 ; j++ ){.
            System.out.println("j的值是" + j);
       if (j == 1){
         // 忽略本次,循环的剩下语句,就是除了j=1不打印以外其他的都打印
         continue;
       }
       System.out.println("continue后的输出语句");
    }
  }
}

break

break用于完全结束一个循环,跳出循环体。不管是哪种循环,一旦在循环体中遇到break,系统将完全结束循环,开始执行循环之后的代码。 break不仅可以结束其所在的循环,还可结束其外层循环。此时需要在break后紧跟一个标签,这个标签用于标识一个外层循环。Java中的标签就是一个紧跟着英文冒号(:)的标识符。且它必须放在循环语句之前才有作用。

public class BreakTest
{
  public static void main(String[] args){
    // 外层循环,outer作为标识符
    outer:
    for (int i = 0 ; i < 5 ; i++ ){
      // 内层循环
      for (int j = 0; j < 3 ; j++ ){
        System.out.println("i的值为:" + i + " j的值为:" + j);
        if (j == 1){
          // 跳出outer标签所标识的循环。
           break outer;
        }
      }
    }
  }
}

骚戴理解:注意break本身只能跳出一层循环,像上面的的第二层循环能跳出,但是不会跳出第一层循环,但是结合标识符就可以跳出多层嵌套循环

在 Java 中,如何跳出当前的多重嵌套循环

在Java中,要跳出当前的多重嵌套循环,可以使用标签(label)和break语句结合使用。例如:

outer: 
for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (j == 5) {
            break outer;
        }
        System.out.println("i=" + i + ", j=" + j);
    }
}

骚戴理解:在上面的代码中,使用outer标签标记了外层循环,在内层循环中,当j等于5时,使用break outer语句跳出多重嵌套循环。当程序执行到这个语句时,会跳转到outer标签处,从而跳出多重嵌套循环。 注意上面的代码在执行到 `break outer;` 时,会立即跳出多重循环,不会继续执行之后的代码。

面向对象

面向对象和面向过程

面向过程的优缺点

优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发,性能是最重要的因素。

缺点:没有面向对象易维护、易复用、易扩展

面向对象的优缺点

优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护

缺点:性能比面向过程低

面向对象和面向过程的区别

面向对象和面向过程是两种不同的编程思想。面向过程是按照步骤一步一步地解决问题,强调的是数据和行为的分离;而面向对象则是将问题看作是由许多对象组成的,强调的是数据和行为的统一。面向过程的程序设计更加注重程序的执行过程,而面向对象的程序设计更加注重对象之间的交互。在面向对象的程序设计中,我们将问题看作是由许多对象组成的,每个对象都有自己的属性和方法,对象之间通过方法来进行交互,从而完成程序的功能。而在面向过程的程序设计中,我们则是按照步骤一步一步地解决问题,强调的是数据和行为的分离。

java中子类会继承父类的构造方法吗?

Java中的子类会默认继承父类的构造方法,但是子类的构造方法并不完全继承父类的构造方法。具体来说,子类构造方法会自动调用父类的无参构造方法,如果父类没有无参构造方法,则需要在子类的构造方法中显式调用父类的有参构造方法。如果子类的构造方法没有显式调用父类的构造方法,则编译器会自动在子类的构造方法中插入一条隐式的调用语句 `super();`,该语句会调用父类的无参构造方法。如果父类没有无参构造,然后子类又没有显性的引用父类的有参构造的话就会报错!

如果父类中有多个构造方法,子类可以选择调用其中一个构造方法,也可以在自己的构造方法中添加额外的参数,以便调用父类的有参构造方法。

需要注意的是,如果父类中的构造方法是private类型的,则子类无法继承该构造方法,因为private类型的构造方法只能在本类中访问,无法被子类继承和调用。

总之,Java中的子类会默认继承父类的构造方法,但需要注意构造方法的访问控制符以及在子类构造方法中是否显式调用了父类的构造方法。

java中子类会继承父类的private方法和属性吗?

Java中的子类不会继承父类的私有(private)方法和属性。私有方法和属性只能在本类中访问,无法被子类继承和访问。这是因为私有方法和属性的访问控制符是private,只能在本类中被访问,其他类无法访问。因此,子类无法继承父类的私有方法和属性。

如果父类中有一些私有方法和属性需要在子类中使用,可以将其改为protected类型,这样子类就可以继承和访问了。protected类型的方法和属性可以被子类继承和访问,同时也可以在同一包内的其他类中访问。

需要注意的是,如果父类中的方法和属性是default类型(即没有访问控制符),则子类可以继承和访问,但是只限于同一包内的子类。如果子类和父类不在同一包内,则无法继承和访问父类的default方法和属性。

面向对象的特征有哪些方面

1、抽象

抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。

其中Java 面向对象编程三大特性:封装 继承 多态

2、封装

Java的特性封装是通过使用访问控制符,我们可以将类的内部实现细节隐藏起来,只暴露出必要的接口,从而保证了数据的安全性和完整性。

在Java中,封装是通过访问控制符来实现的。Java提供了四种访问控制符:public、protected、private和default。其中,public表示公共的,可以在任何地方访问;protected表示受保护的,只能在当前类、同一包内的类和子类中访问;private表示私有的,只能在当前类中访问;default表示默认的,只能在同一包内的类中访问。

3、继承

继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。

关于继承如下 3 点请记住:

1、子类拥有父类非 private 的属性和方法。

2、子类可以拥有自己属性和方法,即子类可以对父类进行扩展。

3、子类可以用自己的方式实现父类的方法(重写)。

4、多态

Java的特性多态是指同一种行为或方法可以在不同的对象上具有不同的实现方式和表现形式。具体来说,多态性是指一个对象可以被看作是多种类型的实例,这些类型可以是它本身的类型,也可以是它的父类或接口的类型。

Java中的多态性主要通过两种方式实现:继承和接口。

  • 通过继承,子类可以继承父类的方法和属性,同时也可以重写父类的方法,从而实现不同的行为。
  • 通过接口,类可以实现多个接口,从而具有多种行为和表现形式。

在Java中,多态性的实现主要依赖于动态绑定机制。在程序运行时,系统会根据对象的实际类型来调用相应的方法,而不是根据变量的类型来调用方法。这样就可以实现同一种方法在不同对象上的不同实现方式和表现形式,从而实现多态性。

多态性的好处是可以提高程序的灵活性和可扩展性,同时也可以提高代码的可读性和可维护性。因此,在Java程序设计中,多态性是一个非常重要的特性。

什么是多态机制?Java语言是如何实现多态的?

什么是多态机制?

多态机制是一种面向对象编程的机制,多态是指同一种行为或方法可以在不同的对象上具有不同的实现方式和表现形式。具体来说,多态性是指一个对象可以被看作是多种类型的实例,这些类型可以是它本身的类型,也可以是它的父类或接口的类型。

Java语言是如何实现多态的?

Java语言是一种支持多态机制的编程语言,它通过继承和接口实现多态性。

Java中的多态性是通过动态绑定(Dynamic Binding)实现的。动态绑定是指在运行时根据对象的实际类型来确定调用哪个方法或属性。当一个方法被调用时,编译器并不知道实际调用的是哪个方法,而是在运行时根据对象的实际类型来确定调用哪个方法。这样就可以实现同一种方法在不同对象上的不同实现方式和表现形式,从而体现多态性。

具体来说,Java中的多态性主要通过两种方式实现:继承和接口。通过继承,子类可以继承父类的方法和属性,同时也可以重写父类的方法,从而实现不同的行为。通过接口,类可以实现多个接口,从而具有多种行为和表现形式。

在Java中,多态性的实现主要依赖于动态绑定机制。在程序运行时,系统会根据对象的实际类型来调用相应的方法,而不是根据变量的类型来调用方法。这样就可以实现同一种方法在不同对象上的不同实现方式和表现形式,从而实现多态性。

总之,Java中的多态机制是一种非常重要的面向对象编程的机制,它可以提高程序的灵活性和可扩展性,同时也可以提高代码的可读性和可维护性。

面向对象五大基本原则是什么

1、单一职责原则SRP(Single Responsibility Principle)

类的功能要单一,不能包罗万象,跟杂货铺似的。

2、开放封闭原则OCP(Open-Close Principle)

一个模块对于拓展是开放的,对于修改是封闭的

3、里式替换原则LSP(the Liskov Substitution Principle LSP)

子类可以替换父类出现在父类能够出现的任何地方。

4、依赖倒置原则DIP(the Dependency Inversion Principle DIP)

依赖倒置原则(Dependency Inversion Principle,简称DIP)是面向对象设计中的一条重要原则,它是SOLID原则中的一部分。它的核心思想是:高层模块不应该依赖于低层模块,二者都应该依赖于抽象,抽象不应该依赖于细节,而细节应该依赖于抽象。

这个原则的意思是,我们在设计类和模块时,应该尽量使用抽象类或接口来定义类之间的依赖关系,而不是使用具体的实现类。这样做的好处是,可以降低模块之间的耦合度,提高代码的可维护性和可扩展性。同时,也可以提高代码的重用性和测试性。

具体来说,依赖倒置原则可以通过以下几个方面来实现:

1. 高层模块不应该依赖于低层模块:这意味着我们应该尽量避免在高层模块中直接使用低层模块的具体实现类,而应该使用抽象类或接口来定义依赖关系。

2. 二者都应该依赖于抽象:这意味着我们应该尽量使用抽象类或接口来定义类之间的依赖关系,而不是使用具体的实现类。

3. 抽象不应该依赖于细节:这意味着我们应该尽量避免在抽象类或接口中使用具体的实现类,而应该将细节留给具体的实现类去处理。

4. 细节应该依赖于抽象:这意味着我们应该尽量使用抽象类或接口来定义类之间的依赖关系,而具体的实现类应该依赖于抽象类或接口。

总之,依赖倒置原则是一条非常重要的面向对象设计原则,它可以帮助我们设计出更加灵活、可维护、可扩展和可测试的代码。

5、接口分离原则ISP(the Interface Segregation Principle ISP)

接口分离原则(Interface Segregation Principle,简称ISP)是面向对象设计中的一条重要原则,它是SOLID原则中的一部分。它的核心思想是:一个类不应该依赖于它不需要的接口,一个类应该尽量少地依赖于其他类。

这个原则的意思是,我们在设计接口时,应该尽量将接口拆分成多个小的、专门的接口,而不是设计一个大而全的接口。这样做的好处是,可以降低类之间的耦合度,提高代码的可维护性和可扩展性。同时,也可以提高代码的重用性和灵活性。

具体来说,接口分离原则可以通过以下几个方面来实现:

1. 将接口拆分成多个小的、专门的接口:这意味着我们应该尽量将接口中的方法拆分成多个小的、专门的接口,而不是设计一个大而全的接口。

2. 避免接口过于臃肿:这意味着我们应该尽量避免在接口中定义过多的方法,而应该将方法拆分成多个小的、专门的接口。

3. 接口与实现相分离:这意味着我们应该尽量将接口与实现相分离,将接口定义在独立的模块中,而具体的实现类则实现接口。

4. 不强制实现不需要的接口:这意味着我们应该尽量避免在一个类中实现不需要的接口,而应该只实现该类需要的接口。

总之,接口分离原则是一条非常重要的面向对象设计原则,它可以帮助我们设计出更加灵活、可维护、可扩展和可测试的代码。

抽象类和接口的对比

抽象类和接口都是Java中实现抽象的机制,但是它们有一些异同之处。

相同点:

1. 都不能被实例化,只能被继承或实现。

2. 都可以包含抽象方法,需要子类或实现类去实现。

3. 都可以包含具体的方法实现。

4. 都可以用来实现多态性。

不同点:

1. 抽象类可以包含抽象方法和具体方法,而接口只能包含抽象方法。

2. 一个类只能继承一个抽象类,但是可以实现多个接口。

3. 抽象类可以有构造方法,而接口没有构造方法。

4. 抽象类的子类可以覆盖父类的方法,也可以不覆盖,而实现接口的类必须实现接口中的所有方法。

5. 抽象类可以有成员变量,而接口只能有常量。

6. 抽象类的访问修饰符可以是public、protected或默认的,而接口的访问修饰符只能是public。

7. 抽象类用于表示一种“is-a”的关系,即子类是父类的一种特殊类型,而接口用于表示一种“has-a”的关系,即类具有某种能力或特征。

总之,抽象类和接口都是Java中实现抽象的机制,它们都有自己的优缺点和适用场景,我们需要根据具体的需求来选择使用哪种方式。

java中接口的方法能不能有方法体?

在Java 8之前,接口中的方法都是抽象方法,不能有方法体。但是,从Java 8开始,接口中可以定义默认方法(default method)和静态方法(static method),这两种方法都可以有方法体。

默认方法是指在接口中定义的有方法体的方法,可以被实现该接口的类直接继承或重写。默认方法的关键字是default,例如:


public interface MyInterface {
    default void myMethod() {
        System.out.println("This is a default method.");
    }
}

静态方法是指在接口中定义的有方法体的静态方法,可以直接通过接口名调用。静态方法的关键字是static,例如:


public interface MyInterface {
    static void myStaticMethod() {
        System.out.println("This is a static method.");
    }
}

需要注意的是,接口中的默认方法和静态方法都有方法体,但是抽象方法没有方法体。默认方法和静态方法的出现使得接口的功能更加强大,可以更好地支持代码的复用和扩展。

普通类和抽象类有哪些区别?

普通类和抽象类的主要区别在于:

1. 实例化:普通类可以被直接实例化,而抽象类不能被直接实例化,只能被继承。

2. 抽象方法:普通类中不能包含抽象方法,而抽象类中可以包含抽象方法。

3. 方法实现:普通类中的方法必须有具体的实现,而抽象类中的抽象方法没有具体的实现,需要子类去实现。

4. 继承:普通类可以被其他类继承,而抽象类只能被继承,不能被实例化。

5. 关系:普通类表示一种具体的对象,而抽象类表示一种抽象的概念或模板。

6. 使用:普通类通常用于封装数据和行为,而抽象类通常用于定义一些通用的行为和属性,以便子类继承和实现。

总之,普通类和抽象类都是Java中的类,它们有自己的特点和适用场景。我们需要根据具体的需求来选择使用哪种类型的类。

骚戴理解:需要注意的是抽象类里面可以有抽象方法和非抽象方法(也就是有方法体的方法),所以抽象类里的方法不一定都是抽象方法,但是如果一个类里有抽象方法,那么这个类一定是抽象类

抽象类能使用 final 修饰吗?

不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,所以 final 不能修饰抽象类

创建一个对象用什么关键字?对象实例与对象引用有何不同?

new关键字

对象实例与对象引用有何不同?

  • new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放在栈内存中)。
  • 在Java中,一个对象引用可以指向0个或1个对象【一个对象引用可以为null,表示它没有指向任何对象】。同时,一个对象可以有n个引用指向它,也就是说,多个对象引用可以指向同一个对象实例。这种情况下,我们可以通过任意一个对象引用来访问该对象实例的数据和方法。这种多个引用指向同一个对象实例的情况,在Java中被称为对象的共享(Object Sharing)。对象的共享可以节省内存空间,提高程序的效率

解释java中的变量、成员变量、局部变量的概念

在Java中,变量是指在内存中分配的一块空间,用于存储数据。Java中的变量分为以下两种类型:

1. 局部变量:定义在方法、代码块或者方法的参数列表中,只在定义它的方法、代码块或者参数列表中有效,出了这个范围就无法访问。局部变量必须显式地初始化,否则编译器会报错。

2. 成员变量:定义在类中,方法外,可以被类中的所有方法访问。成员变量有默认值,如果没有显式地初始化,会根据类型自动赋予默认值。成员变量可以有不同的访问权限,例如public、private、protected和默认的访问权限。

成员变量与局部变量的区别有哪些

成员变量和局部变量是Java中的两种变量,它们有以下区别:

  1. 定义位置:成员变量定义在类中,方法外;局部变量定义在方法中、代码块中或者方法的参数列表中。

  2. 作用域:成员变量的作用域是整个类,可以被类中的所有方法访问;局部变量的作用域仅限于定义它的方法、代码块或者参数列表。

  3. 生命周期:成员变量的生命周期与对象的生命周期一样,当对象被创建时,成员变量就被创建;当对象被销毁时,成员变量也被销毁。局部变量的生命周期在方法、代码块或者参数列表执行完毕后就结束了。

  4. 默认值:成员变量有默认值,例如int类型的成员变量默认值为0;局部变量没有默认值,必须在使用之前进行初始化。

  5. 访问权限:成员变量可以有不同的访问权限,例如public、private、protected和默认的访问权限;局部变量没有访问权限的概念。

  6. 内存分配:成员变量在对象创建时分配内存空间;局部变量在定义时分配内存空间,当作用域结束时,内存空间被释放。

使用原则

在Java中,使用变量时需要遵循就近原则(Nearby Principle),即优先使用离当前位置最近的变量。就近原则的具体实现方式如下:

1. 首先在当前作用域(方法、代码块、参数列表)中查找变量,如果找到了同名的变量,就使用它。

2. 如果在当前作用域中没有找到同名的变量,就在外层作用域(如果有的话)中查找同名的变量,直到找到为止。

3. 如果在所有作用域中都没有找到同名的变量,就会报编译错误。

需要注意的是,如果局部变量和成员变量同名,就近原则会优先使用局部变量,如果要使用成员变量,需要使用this关键字来指定。

在Java中定义没有参数的构造方法(无参构造)的作用

在Java中,定义没有参数的构造方法的作用主要有以下两个方面:

1. 初始化对象的成员变量:Java中的无参构造方法可以在对象创建时对成员变量进行初始化,确保对象在使用之前具有合理的状态。如果一个类定义了有参构造方法,那么子类必须显式地调用父类的有参构造方法,以确保父类的成员变量得到了初始化。

2. 方便对象的创建:定义无参构造方法可以方便对象的创建,不需要在创建对象时传入参数。这在某些场景下非常有用,例如创建一个默认配置的对象或者创建一个对象池。

需要注意的是,如果一个类没有定义构造方法,Java会提供默认的无参构造方法;如果一个类定义了有参构造方法,但是没有定义无参构造方法,那么在创建对象时必须传入参数,否则编译器会报错。因此,无论是否需要在构造方法中进行初始化操作,都建议定义一个无参构造方法,以便在需要时使用。

在调用子类构造方法之前会先调用父类没有参数的构造方法,其目的是?

在Java中,如果一个类没有定义任何构造方法,Java会提供默认的无参构造方法。如果一个类定义了构造方法,但是没有定义无参构造方法,那么在创建对象时必须调用有参构造方法,并传入必要的参数。如果一个子类没有显式地调用父类的构造方法,那么编译器会自动在子类的构造方法中插入一条调用父类无参构造方法的语句,即super()。

调用父类无参构造方法的目的是确保父类的成员变量在子类对象创建之前得到了初始化。如果父类没有定义无参构造方法,而子类又没有显式地调用父类的有参构造方法,那么编译器就会报错。因此,如果父类定义了有参构造方法,那么子类必须显式地调用父类的有参构造方法,以确保父类的成员变量得到了初始化。

总之,调用父类无参构造方法的目的是确保父类的成员变量在子类对象创建之前得到了初始化,如果父类没有定义无参构造方法,那么子类必须显式地调用父类的有参构造方法。

一个类的构造方法的作用是什么?若一个类没有声明构造方法,程序能正确执行吗?为什么?

一个类的构造方法的作用是什么?

一个类的构造方法的作用是在创建对象时对对象进行初始化,可以用来初始化对象的成员变量,确保对象在使用之前具有合理的状态。

骚戴理解:对于合理的状态的理解如下

在Java中,一个对象的状态是由其成员变量的值决定的。一个对象处于合理的状态意味着它的成员变量具有合理的值,能够正常地执行其设计的功能。例如,一个Person类的对象,在创建时应该具有合理的姓名、年龄、性别等成员变量的值,以便在程序中正确地使用这些信息。

构造方法的作用之一就是确保对象在创建时处于合理的状态。通过在构造方法中对成员变量进行初始化,可以确保对象在使用之前具有合理的状态,避免出现未初始化或不合理的状态。例如,如果一个Person类的对象没有初始化姓名、年龄、性别等成员变量,那么在程序中使用这些信息时就会出现错误,导致程序崩溃或产生不正确的结果。

因此,一个类的构造方法的作用是确保对象在创建时处于合理的状态,即其成员变量具有合理的值,能够正常地执行其设计的功能。

若一个类没有声明构造方法,程序能正确执行吗?为什么?

可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。

构造方法有哪些特性?

Java中的构造方法有以下几个特性:

1. 构造方法的名称必须与类名相同,且没有返回类型,包括void类型。

2. 构造方法可以有不同的参数列表,包括无参构造方法、有参构造方法以及重载构造方法等。

3. 如果一个类没有定义任何构造方法,Java会提供默认的无参构造方法,如果定义了构造方法,但没有定义无参构造方法,那么在创建对象时必须调用有参构造方法,并传入必要的参数。

4. 构造方法在创建对象时自动调用,用于初始化对象的成员变量,确保对象在使用之前具有合理的状态。

5. 构造方法可以调用其他方法或父类的构造方法,并可以使用this和super关键字来访问当前对象和父类对象。

6. 如果一个子类没有显式地调用父类的构造方法,那么编译器会自动在子类的构造方法中插入一条调用父类无参构造方法的语句,即super()。

7. 如果一个类定义了有参构造方法,那么子类必须显式地调用父类的有参构造方法,以确保父类的成员变量得到了初始化。

总之,构造方法是一种特殊的方法,用于在创建对象时对对象进行初始化。构造方法的名称必须与类名相同,没有返回类型,可以有不同的参数列表。构造方法可以调用其他方法或父类的构造方法,并可以使用this和super关键字来访问当前对象和父类对象。在使用构造方法时需要注意调用顺序和传入参数的正确性,以确保对象在使用之前处于合理的状态。

骚戴理解:这里我一直以为构造器只能是public修饰,这是错误的!

静态变量和实例变量(普通变量)区别

静态变量: 静态变量由于不属于任何实例对象,属于类的,所以在内存中只会有一份,在类的加载过程中,JVM只为静态变量分配一次内存空间。

实例变量(普通变量): 每次创建对象,都会为每个对象分配成员变量内存空间,实例变量是属于实例对象的,在内存中,创建几次对象,就有几份成员变量。

静态方法和实例方法有何不同?

1、在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有 后面这种方式。也就是说,调用静态方法可以无需创建对象。

2、静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法),实例方法则无此限制

在一个静态方法内调用一个非静态成员为什么是非法的?

在一个静态方法内调用一个非静态成员是非法的,因为静态方法和非静态成员是属于不同的类成员,它们的访问方式和作用域不同。

静态方法是属于类的方法,它不依赖于任何对象的实例,可以直接通过类名调用。静态方法只能访问静态成员,因为静态成员在类加载时已经被初始化,不依赖于对象的实例。

非静态成员是属于对象的成员,它必须通过对象的实例来访问。非静态成员只能在对象创建后才能被访问,因为它们的值是与对象的实例相关的。

因此,在一个静态方法内调用一个非静态成员是非法的,因为静态方法不依赖于对象的实例,不能直接访问非静态成员。如果需要在静态方法中访问非静态成员,可以通过创建对象的实例来访问,或者将非静态成员改为静态成员。

什么是方法的返回值?返回值的作用是什么?

方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。

返回值的作用:接收方法产生的结果,使得它可以用于其他的操作!

什么是内部类?

在Java中,可以将一个类的定义放在另外一个类的定义内部,这就是内部类。

内部类本身就是类的一个属性,与其他属性定义方式一致。

内部类的分类有哪些

Java中的内部类可以分为以下四种:

1. 成员内部类(Member Inner Class):成员内部类是定义在另一个类中的类,它可以访问外部类的所有成员变量和方法,包括私有成员。成员内部类可以被声明为static或非static,如果声明为static,则称为静态内部类。

2. 局部内部类(Local Inner Class):局部内部类是定义在方法或作用域内的类,它只能在该方法或作用域内访问,不能被其他方法或作用域访问。局部内部类可以访问外部类的所有成员变量和方法,但是只能访问final或effectively final的局部变量。

3. 匿名内部类(Anonymous Inner Class):匿名内部类是没有类名的内部类,它通常用于创建实现了某个接口或继承了某个类的对象。匿名内部类可以访问外部类的所有成员变量和方法,但是不能定义构造方法,因为它没有类名。

4. 静态内部类(Static Inner Class):静态内部类是定义在另一个类中的static类,它不能访问外部类的非static成员,只能访问外部类的static成员。静态内部类可以被直接访问,不需要先创建外部类的对象。

1、静态内部类

定义在类内部的静态类,就是静态内部类。

public class Outer {
      private static int radius =1;
       //静态内部类
      static class StaticInner{ 
        public void visit(){
	        System.out.println("visit outer static variable:"+ radius);
        }
      }
}

静态内部类可以访问外部类所有的静态变量,但是不可访问外部类的非静态变量;

静态内部类的创建方式,new 外部类.静态内部类(),如下:

Outer.StaticInner inner =new Outer.StaticInner();

inner.visit();

骚戴理解:静态内部类里面定义的方法不一定都是静态方法。静态内部类是一个独立的类,它可以包含静态成员和非静态成员,也可以包含静态方法和非静态方法

2、成员内部类

定义在类内部,成员位置上的非静态类,就是成员内部类。

public class Outer {
    private static int radius =1;
    privateint count =2;
    class Inner{
        public void visit(){	
            System.out.println("visit outer static  variable:"+ radius);	
            System.out.println("visit outer variable:"+ count);
      }
   }
}

成员内部类可以访问外部类所有的变量和方法,包括静态和非静态,私有和公有。

成员内部类依赖于外部类的实例,它的创建方式外部类实例.new 内部类(),如下:

Outer outer =new Outer();

Outer.Inner inner = outer.new Inner();

inner.visit();

骚戴理解:可以看出静态内部类和成员内部类在定义方面只是差了一个static

3、局部内部类

定义在方法中的内部类,就是局部内部类。

public class Outer{
    private int out_a =1;
    private static int STATIC_b =2;
    public void test FunctionClass(){
        int inner_c=3;
        class Inner{
            private void fun(){		
                System.out.println(out_a);	
                System.out.println(STATIC_b); 
                System.out.println(inner_c);
                }
             }	
                Inner  inner =new Inner();	//直接在方法里用new创建局部内部类
                inner.fun();
           }

        public static void test StaticFunctionClass(){
            int d=3;
            class Inner{
                private void fun(){
                    //System.out.println(out_a); 
                    //编译错误,定义在静态方法中的局部类不可以访问外部类的实例变量
                    System.out.println(STATIC_b);	
                    System.out.println(d);
                    }
                }	
                    Inner  inner =new Inner();	//直接在方法里用new创建局部内部类
                    inner.fun();
      }
} 

定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和静态方法 。

局部内部类的创建方式 ,在对应方法内 new 内部类(), 如下 :

public static void testStaticFunctionClass(){
  class Inner{} 
  Inner inner =new Inner();
}

4、匿名内部类

匿名内部类就是没有名字的内部类

匿名内部类举例

红色框画出来的就是一个匿名内部类同时重写了父类Animals的eat方法,并且调用了这个匿名内部类的eat方法

如何调用匿名内部类中的方法?

1、匿名内部类中只有一个方法的情况

2、匿名内部类有多个方法

第一种方式

第二种方式

如果想调用匿名内部类自己特有的方法的时候呢?该如何调用呢?

骚戴理解:简单来说就是这个实现不了,匿名内部类无法调用自己特有的接口,直接调用会报错,它只能调用继承的类或实现的接口里有的方法,例如上面的run方法就是上面匿名内部类特有的方法,这样的方法是无法调用的

匿名内部类实现接口

匿名内部类存在的前提是要有继承或者实现关系的,但是并没有看到extends和implements关键字,这是怎么回事呢?

答:在使用匿名内部类时,确实需要有继承或者实现关系,但是并不需要使用extends和implements关键字来显示地声明继承或实现关系。这是因为在匿名内部类的定义中,已经隐含了继承或实现的关系。这些由jvm搞定了。

匿名内部类的特点

除了没有名字,匿名内部类还有以下特点:

1、匿名内部类必须继承一个抽象类或者实现一个接口。

2、匿名内部类不能定义任何静态成员和静态方法。

3、匿名内部类访问局部变量的时候,必须把局部变量声明为 final。

4、匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。

匿名内部类创建方式:

new 类/接口{

    //匿名内部类实现部分

}

 内部类的优点

内部类是Java中一种特殊的类,它定义在另一个类的内部。内部类具有以下几个优点:

1. 封装性:内部类可以访问外部类的私有成员,而外部类不能访问内部类的私有成员。这样可以实现更好的封装性,防止外部类直接访问内部类的私有成员。

2. 继承性:内部类可以继承外部类,而且可以多重继承。这样可以实现更灵活的继承关系

3. 多态性:内部类可以实现接口或继承抽象类,从而实现多态性。这样可以更好地支持面向对象编程的特性,如封装、继承和多态。

4. 代码组织性:内部类可以将相关的代码组织在一起,从而提高代码的可读性和可维护性。内部类可以访问外部类的成员,从而可以更方便地实现某些功能。

5. 回调函数:内部类可以用作回调函数,从而实现更灵活的事件处理机制。内部类可以访问外部类的成员,从而可以更方便地处理事件。

总之,内部类是Java中一种非常有用的特性,它可以提高代码的封装性、继承性、多态性、代码组织性和灵活性,可以帮助我们更好地实现面向对象编程的特性。

内部类有哪些应用场景 

内部类是Java中一种特殊的类,它定义在另一个类的内部。内部类具有以下几个应用场景:

1. 实现回调函数:内部类可以用作回调函数,从而实现更灵活的事件处理机制。内部类可以访问外部类的成员,从而可以更方便地处理事件。

2. 实现多重继承:内部类可以继承外部类,而且可以多重继承。这样可以实现更灵活的继承关系,可以避免多重继承的一些问题。

3. 实现接口:内部类可以实现接口或继承抽象类,从而实现多态性。这样可以更好地支持面向对象编程的特性,如封装、继承和多态。

4. 封装性:内部类可以访问外部类的私有成员,而外部类不能访问内部类的私有成员。这样可以实现更好的封装性,防止外部类直接访问内部类的私有成员。

5. 代码组织性:内部类可以将相关的代码组织在一起,从而提高代码的可读性和可维护性。内部类可以访问外部类的成员,从而可以更方便地实现某些功能。

6. 实现迭代器:内部类可以用于实现迭代器,从而实现更灵活的遍历方式。内部类可以访问外部类的成员,从而可以更方便地实现迭代器的功能。

总之,内部类是Java中一种非常有用的特性,它可以提高代码的封装性、继承性、多态性、代码组织性和灵活性,可以帮助我们更好地实现面向对象编程的特性。内部类在实际开发中有着广泛的应用场景。

局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final? 

在Java中,局部内部类和匿名内部类访问局部变量时,如果这些变量没有被声明为final,编译器会报错。这是因为Java要求在内部类中访问局部变量时,这些变量必须是final或者是实际上的final。

这是因为内部类和外部类是两个独立的作用域,内部类可以访问外部类的成员变量和方法,但是不能直接访问外部类的局部变量。为了让内部类能够访问外部类的局部变量,Java采用了将这些变量复制一份到内部类中的方式。但是,如果这些变量不是final或实际上的final,那么在复制的过程中,这些变量的值可能会被修改,从而导致内部类和外部类的值不一致。

为了避免这种情况的发生,Java要求在内部类中访问局部变量时,这些变量必须是final或者是实际上的final。这样,在复制变量的值到内部类中时,就可以保证这些变量的值不会被修改,从而保证内部类和外部类的值一致。

需要注意的是,Java8之后,如果变量是final或者是实际上的final,那么就不需要显式地声明为final,编译器会自动将它们视为final变量。但是,如果变量被修改了,编译器仍然会报错。

总之,Java要求在内部类中访问局部变量时,这些变量必须是final或者是实际上的final,这是为了保证内部类和外部类的值一致。

匿名内部类为什么不能定义任何静态成员和静态方法

匿名内部类是一种没有名字的内部类,它是在创建对象时动态生成的一个类。因为匿名内部类没有名字,所以它无法被其他类所引用,也无法被继承或扩展。

静态成员和静态方法是属于类的成员,它们在类加载时就已经被初始化,而不是在对象创建时才被初始化。由于匿名内部类没有名字,它在类加载时无法被初始化静态成员和静态方法,因此不能定义任何静态成员和静态方法。

可以这样理解,静态成员和静态方法是属于类的,而匿名内部类是属于对象的,它只是在创建对象时动态生成的一个类。因此,匿名内部类不能定义静态成员和静态方法,就好像一个人没有名字,就无法拥有自己的财产一样。

总之,匿名内部类是一种没有名字的内部类,它无法被其他类所引用,也无法被继承或扩展。由于它没有名字,无法在类加载时被初始化静态成员和静态方法,因此不能定义任何静态成员和静态方法。

构造器(constructor)是否可被重写(override) 

构造器(constructor)不是普通的方法,因此不能像方法一样被重写(override)。构造器是用来创建对象的特殊方法,它在创建对象时被调用,用来初始化对象的成员变量。每个类都有自己的构造器,如果没有显式地定义构造器,Java会自动生成一个默认的构造器。

虽然构造器不能被重写,但是可以通过继承来实现构造器的复用。子类可以使用super关键字调用父类的构造器,从而实现对父类构造器的重用。如果子类没有显式地调用父类的构造器,Java会默认调用父类的无参构造器。如果父类没有无参构造器,子类必须显式地调用父类的带参构造器。

需要注意的是,子类的构造器必须先调用父类的构造器,然后再进行自己的初始化操作。如果子类没有显式地调用父类的构造器,Java会默认调用父类的无参构造器,如果父类没有无参构造器,编译会出错。因此,在使用继承时需要注意构造器的调用顺序和参数传递问题。

重载(Overload)和重写(Override)的区别? 

重载(Overload)和重写(Override)是Java中两个重要的概念,它们的区别如下:

1. 定义:重载指在同一个类中定义多个同名但参数类型或个数不同的方法;重写指在子类中重新定义父类中已有的方法。

2. 参数:重载方法的参数类型或个数必须不同,否则会出现编译错误;重写方法的参数类型和个数必须与父类中被重写的方法相同。

3. 返回值:重载方法的返回值类型可以相同也可以不同,但是不能只有返回类型不同;重写方法的返回值类型必须与父类中被重写的方法相同或是其子类。

4. 访问修饰符:重载方法可以具有不同的访问修饰符,但是不能比父类中被重载的方法的访问修饰符更严格;重写方法的访问修饰符必须比父类中被重写的方法的访问修饰符更宽松。

5. 静态方法:重载可以包括静态方法,但是不能只有静态性质不同;重写方法不能是静态方法。

6. 父类和子类:重载方法必须在同一个类中定义;重写方法必须在子类中定义。

重载的方法能否根据返回类型进行区分? 

在Java中,重载的方法不能仅根据返回类型进行区分。这是因为Java编译器在重载方法时,只会考虑方法名和参数列表,而不会考虑返回类型。如果两个方法的方法名和参数列表相同,但是返回类型不同,那么编译器会认为这是两个相同的方法,从而导致编译错误。

例如,下面的代码就会导致编译错误:

```
public class Test {
    public void foo() {}
    public int foo() { return 0; }
}
```

这是因为上面的代码中定义了两个同名、参数列表相同但返回类型不同的方法,编译器无法区分它们,从而导致编译错误。

== 和 equals 的区别是什么 

== : 它的作用是判断两个对象的地址是不是相等。即判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)

equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:

  • 情况1:如果一个类没有重写“equals”方法,那么它将继承Object类的“equals”方法,该方法比较的是两个对象的内存地址是否相同,即与“==”比较的结果相同
  • 情况2:如果重写了equals方法,那么就是比较内容是否相同,例如String类的equals方法就是重写了的

举个例子:

public class test1{
    public static void main(String[] args){	
    String a =new String("ab");// a 为一个引用	
    String b=new String("ab");// b为另一个引用,对象的内容一样	
    String aa ="ab";// 放在常量池中	
    String bb ="ab";// 从常量池中查找
    if(aa == bb)// true	
    System.out.println("aa==bb");
    if(a == b)// false,非同一对象
    System.out.println("a==b");
    if(a.equals(b))// true		
    System.out.println("aEQb");
    if(42==42.0){// true
     System.out.println("true");
      }
   }
}

骚戴理解:String中的equals方法是被重写过的,所以String的equals方法比较的是对象的内容是否相同。

java中常量放在jvm的堆还是方法区

在Java中,常量一般放在方法区中,而不是放在JVM的堆中。方法区是一块用于存储类的元数据、静态变量、常量、类信息等的内存区域,它是线程共享的,与堆一样也是被整个JVM所共享的。

具体来说,Java中的常量包括两种类型:字面常量和符号常量。字面常量是指代码中直接使用的常量值,比如字符串、数字、布尔值等;而符号常量是指使用final关键字定义的常量,它们的值在编译时就已经确定,并且不能被修改。

对于字面常量,它们通常是放在JVM的常量池中的,常量池是方法区的一部分,用于存储编译时生成的各种字面常量和符号引用。常量池中的常量可以被多个线程共享,而且它们的生命周期与类的生命周期相同。

对于符号常量,它们通常是放在方法区的静态变量中的,也就是说,它们的值在类加载时就已经确定,并且在整个程序的生命周期内都不会被修改。

总之,在Java中,常量一般放在方法区中,常量池和静态变量都是方法区的一部分,用于存储常量和静态变量等信息。

hashCode 与 equals

1、hashCode()介绍

hashCode()的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode()函数。散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)

2、为什么要有 hashCode

hashCode是一个用于快速查找对象的整数值,它可以用于哈希表、集合等数据结构中,以提高数据的查找效率。hashCode方法是一种散列码算法,它可以将任意长度的输入数据映射到固定长度的散列码中,从而方便对数据进行比较和查找

例如:当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同, HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

3、两个对象的 hashCode() 相同,则 equals() 也一定为 true,对吗?

1、如果两个对象相等,则hashcode一定也是相同的

2、两个对象相等,对两个对象调用equals方法返回true

3、两个对象有相同的hashcode值,它们也不一定是相等的

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

如果只重写了 equals 方法,那么默认情况下,假设存了两个自定义的内容相同的对象到Set中,Set 进行去重操作时,会先判断两个对象的 hashCode 是否相同,此时因为没有重写 hashCode 方法,所以会直接执行 Object 中的 hashCode 方法,而 Object 中的 hashCode 方法对比的是两个不同引用地址的对象,那么得到的两个Hash值是不一样的,那么 equals 方法就不会执行了,这两个对象就会被判断为不是相等的,于是就在 Set 集合中插入了两个相同的对象(这里的相同是指的内容相同)。

但是,如果在重写 equals 方法时,也重写了 hashCode 方法,那么在执行判断时会去执行重写的 hashCode 方法,此时对比的是两个对象的所有属性的 hashCode 是否相同,于是调用 hashCode 返回的结果就是 true,再去调用 equals 方法,发现两个对象确实是相等的,于是就返回 true 了,因此 Set 集合就不会存储两个一模一样的数据了,于是整个程序的执行就正常了。

总结

hashCode 和 equals 两个方法是用来协同判断两个对象是否相等的,采用这种方式的原因是可以提高程序插入和查询的速度,如果在重写 equals 时,不重写 hashCode,就会导致在某些场景下,例如将两个相等的自定义对象存储在 Set 集合时,就会出现程序执行的异常,为了保证程序的正常执行,所以我们就需要在重写 equals 时,也一并重写 hashCode 方法才行。

对象的相等与指向他们的引用相等,两者有什么不同? 

在Java中,对象的相等与指向它们的引用相等是两个不同的概念,它们有以下几点不同:

1. 比较方式不同:对象的相等通常使用equals方法进行比较,而指向它们的引用相等通常使用“==”运算符进行比较。

2. 比较结果不同:对象的相等比较的是对象的内容是否相同,而指向它们的引用相等比较的是对象的内存地址是否相同。

3. 对象类型不同:对象的相等适用于所有对象类型,包括基本数据类型和对象类型,而指向它们的引用相等只适用于对象类型。

需要注意的是,如果一个类没有重载equals方法,那么它将继承Object类的equals方法,该方法比较的是两个对象的内存地址是否相同,即与指向它们的引用相等的结果相同。

通俗易懂的讲解为什么 Java 中只有值传递 

在Java中,只有值传递,这是因为Java中的变量在传递给方法时,实际上是将变量的值(即数据的拷贝)传递给方法,而不是将变量本身传递给方法。

可以将变量想象成一个盒子,盒子里装着数据。当一个变量作为参数传递给方法时,实际上是将盒子里的数据复制一份,并将这份数据传递给方法。这就好比你把一个盒子里的东西复制一份给朋友,朋友拿到的是复制品,而不是原来的盒子。同理,方法也拿到的是变量的复制品,而不是原来的变量。

需要注意的是,如果变量是引用类型的变量,那么复制的是变量的值(即内存地址),而不是对象本身。这意味着,如果在方法内部修改了对象的数据,那么在方法外部也能看到这些修改,因为它们都是指向同一个对象的。

总之,Java中只有值传递,因为变量在传递给方法时,实际上是将变量的值(即数据的拷贝)传递给方法,而不是将变量本身传递给方法。因此,在Java中不能直接实现引用传递,但是可以通过修改对象的数据来达到类似于引用传递的效果。

骚戴理解:java中只要值传递,你传递的变量如果是引用类型,那也是把这个变量的内存地址复制一份传过去,重点就在于这里是复制!!!虽然我传递的是内存地址,但是我采用的方法是复制这个内存地址再把复制的传过去,效果是和引用传递一样,但是从定义上来看,由于是复制一份内存地址传递,所以就是值传递!

值传递和引用传递有什么区别 

值传递和引用传递是两种不同的参数传递方式,它们的区别主要在于传递的是变量的值还是变量的引用(内存地址)。

在值传递中,当一个变量作为参数传递给方法时,实际上是将该变量的值(即数据的拷贝)传递给方法,而不是将变量本身传递给方法。在方法内部对该变量进行修改不会影响到原来的变量,因为它们指向的是不同的内存地址。这就好比你把一个盒子复制一份给朋友,朋友拿到的是复制品,而不是原来的盒子。

在引用传递中,当一个变量作为参数传递给方法时,实际上是将该变量的引用(内存地址)传递给方法,而不是将变量的值传递给方法。在方法内部对该变量进行修改会影响到原来的变量,因为它们指向的是同一个内存地址。这就好比你把一个盒子里的东西给朋友,朋友拿到的是原来的盒子,你和朋友都可以修改盒子里的东西。

JDK 中常用的包有哪些 

JDK中常用的包有很多,其中一些常用的包如下:

1. java.lang:包含Java语言的核心类,如基本数据类型、字符串、异常处理等。

2. java.util:包含各种实用工具类,如集合框架、日期和时间处理、随机数生成、正则表达式等。

3. java.io:包含输入输出相关的类,如文件读写、网络通信、对象序列化等。

4. java.net:包含网络编程相关的类,如Socket、URL等。

5. java.awt:包含图形用户界面(GUI)相关的类,如窗口、按钮、文本框等。

6. javax.swing:是AWT的扩展,提供了更多的GUI组件、更好的外观和感觉、更好的事件处理等。

7. java.sql:包含与数据库相关的类,如连接数据库、执行SQL语句、处理结果集等。

8. java.math:包含高精度计算相关的类,如BigDecimal、BigInteger等。

9. java.security:包含与安全相关的类,如加密、数字签名、密钥管理等。

10. java.text:包含文本处理相关的类,如格式化和解析日期、数字、货币等。

除了以上这些常用的包之外,JDK中还有很多其他的包,如XML处理、国际化、反射等。开发者在编写Java程序时需要根据具体的需求选择合适的包

IO流

反射

什么是反射机制? 

反射是Java语言的一种机制,它允许程序在运行时获取对象的类型信息、访问对象的属性和方法,并调用对象的方法。反射机制使得程序可以在运行时动态地创建对象、调用方法、访问属性等,而不需要在编译时确定这些信息。

在Java中,每个类都有一个Class对象,它包含了该类的所有信息,如类名、属性、方法等。通过反射机制,可以获取一个类的Class对象,然后使用该对象来访问类的属性和方法。反射机制可以让程序在运行时动态地创建对象、调用方法、访问属性等,而不需要在编译时确定这些信息。

反射机制在Java中有很多应用,如动态代理、注解处理、框架开发等。但是,由于反射机制需要在运行时动态地获取对象信息,所以会带来一定的性能损失。因此,在使用反射机制时需要注意性能问题,并合理使用缓存等技术来提高程序的效率。

反射机制优缺点

反射机制是Java语言的一种特性,它允许程序在运行时动态地获取对象的类型信息、访问对象的属性和方法,并调用对象的方法。反射机制的优缺点如下:

优点:

1. 动态性:反射机制允许程序在运行时动态地获取对象的类型信息、访问对象的属性和方法,并调用对象的方法,从而使程序具有更大的灵活性和动态性。

2. 扩展性:反射机制可以让程序在运行时动态地创建对象、调用方法、访问属性等,而不需要在编译时确定这些信息,从而使程序具有更好的扩展性。

3. 适用性:反射机制可以应用于很多场景,如动态代理、注解处理、框架开发等,使程序更加灵活和可扩展。

缺点:

1. 性能问题:反射机制需要在运行时动态地获取对象信息,所以会带来一定的性能损失,特别是在频繁调用的情况下,会对程序的性能产生较大的影响。

2. 安全问题:反射机制可以访问对象的私有属性和方法,从而可能破坏程序的安全性。

3. 可读性问题:反射机制使得程序的逻辑更加复杂,代码可读性较差,特别是对于初学者来说,可能会造成困难。

总之,反射机制是Java语言的一种特性,它具有动态性、扩展性和适用性等优点,但也存在性能、安全和可读性等缺点。在使用反射机制时需要权衡其优缺点,并根据具体情况进行选择。

反射机制的应用场景有哪些?

反射机制在Java中有很多应用场景,包括以下几个方面:

1. 动态代理:通过反射机制,可以动态地生成代理对象,从而实现对目标对象的代理操作,如AOP、RPC等。

2. 注解处理:通过反射机制,可以读取和处理注解信息,从而实现对程序的自动化处理,如自动化测试、代码生成等。

3. 框架开发:通过反射机制,可以实现框架的扩展性和灵活性,如Spring框架中的BeanFactory、AOP、IOC等。Spring 通过 XML 配置模式装载 Bean 的过程(根据配置文件里的bean定义,通过反射创建一个bean对象)

4. 反射调试工具:通过反射机制,可以实现反射调试工具,如获取对象的类名、属性、方法等信息,从而方便程序员进行调试和开发。我们在使用JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序;

5. 序列化和反序列化:通过反射机制,可以实现对象的序列化和反序列化,从而实现对象的持久化和传输。

6. 动态加载类和资源:通过反射机制,可以动态地加载类和资源,从而实现程序的动态扩展和更新。

Java获取反射的三种方法

  • 通过对象实例的getClass方法获取 (使用的最少的)
  • 通过Class.forName("路径")实现反射机制 (jdbc驱动)
  • 通过类名.class来实现反射机制
public class Student{
    private int id;    
    String name;
    protected boolean sex;
    public float score;
    } 
public classGet{
    //获取反射机制三种方式
    public static void main(String[] args) throws ClassNotFoundException {
    //方式一(通过建立对象)	
    Student stu =new  Student();
    Class classobj1= stu.getClass();	
    System.out.println(classobj1.getName());
    //方式二(所在通过路径-相对路径)	
    Class classobj2= Class.forName("fanshe.Student");                     
    System.out.println(classobj2.getName());
    //方式三(通过类名)	
    Class classobj3= Student.class;
    System.out.println(classobj3.getName());
    }
}

String 

字符型常量和字符串常量的区别 

字符型常量和字符串常量是Java中的两种常量类型,它们的区别如下:

1. 字符型常量:字符型常量是用单引号括起来的单个字符,如'a'、'b'、'c'等。字符型常量只能包含一个字符,且必须用单引号括起来。

2. 字符串常量:字符串常量是用双引号括起来的一串字符,如"Hello"、"World"等。字符串常量可以包含多个字符,且必须用双引号括起来。

3. 存储方式:字符型常量在内存中以字符的形式存储,而字符串常量在内存中以字符数组的形式存储。

4. 可变性:字符型常量是不可变的,一旦定义,就不能修改。而字符串常量可以通过各种方法进行修改,如拼接、替换、截取等。

5. 比较方式:字符型常量可以使用==运算符进行比较,比较的是字符的ASCII码值。而字符串常量不能使用==运算符进行比较,需要使用equals()方法或compareTo()方法进行比较。

什么是字符串常量池? 

字符串常量池是Java中的一种特殊的内存区域,用于存储字符串常量,以便重复使用。当程序创建一个字符串常量时,如果该字符串常量在常量池中已经存在,则直接返回该字符串常量的引用;如果该字符串常量在常量池中不存在,则将该字符串常量添加到常量池中,并返回该字符串常量的引用。

字符串常量池的优点是可以减少内存的使用,提高程序的性能。因为字符串常量池会缓存字符串常量,以便重复使用,所以可以避免创建重复的字符串常量,从而减少内存的使用。同时,由于字符串常量池是一种特殊的内存区域,它的访问速度比堆内存和栈内存更快,所以可以提高程序的性能。

需要注意的是,字符串常量池中的字符串常量是不可变的,一旦定义,就不能修改。如果程序需要修改字符串常量,应该使用StringBuilder或StringBuffer等可变的字符串类型。

jdk1.8的字符串常量池是在堆内存中吗? 

在JDK1.8中,字符串常量池的位置是在堆内存中,但是和一般的堆内存不同,它是被划分出来的一块特殊的内存区域,称为"永久代"(Permanent Generation),也叫"元空间"(Metaspace)。

在JDK1.8之前,字符串常量池是在方法区中的,但是在JDK1.8之后,方法区被移除了,取而代之的是Metaspace。Metaspace是一种与堆内存分离的内存区域,用于存储类的元数据、静态变量、常量等数据。在Metaspace中,字符串常量池也被移动到了堆内存中。

需要注意的是,在JDK1.8中,字符串常量池也有一些变化。在JDK1.8之前,字符串常量池是固定大小的,当常量池中的字符串对象过多时,会导致OutOfMemoryError错误。但是在JDK1.8中,字符串常量池的大小是不固定的,可以动态调整,避免了OutOfMemoryError错误的问题。同时,JDK1.8中也引入了一种新的字符串常量池实现方式,称为"字符串去重"(String Deduplication),可以进一步减少字符串常量池的内存占用。

String 是最基本的数据类型吗? 

不是。Java 中的基本数据类型只有 8 个 :byte、short、int、long、float、double、char、boolean;除了基本类型(primitive type),剩下的都是引用类型(referencetype),Java 5 以后引入的枚举类型也算是一种比较特殊的引用类型。

这是很基础的东西,但是很多初学者却容易忽视,Java 的 8 种基本数据类型中不包括 String,基本数据类型中用来描述文本数据的是 char,但是它只能表示单个字符,比如 ‘a’,‘好’ 之类的,如果要描述一段文本,就需要用多个char 类型的变量,也就是一个 char 类型数组,比如“你好” 就是长度为2的数组 char[] chars = {‘你’,‘好’};

但是使用数组过于麻烦,所以就有了 String,String 底层就是一个 char 类型的数组,只是使用的时候开发者不需要直接操作底层数组,用更加简便的方式即可完成对字符串的使用。

简单来说就是String类利用了final修饰的char类型数组存储字符,源码如下所示:

private final char value[];

String有哪些特性 

String是Java中的一个类,具有以下特性:

1. 不可变性:String对象一旦创建,就不能被修改。如果需要修改字符串内容,只能创建一个新的String对象。这种不可变性使得String对象在多线程环境下更加安全。

2. 字符串常量池:Java中的字符串常量池是一种特殊的内存区域,用于缓存字符串常量,以便重复使用。String类中的字符串常量都是在字符串常量池中创建的。

3. 比较方式:String类中提供了多种比较字符串的方法,如equals()、equalsIgnoreCase()、compareTo()等。其中,equals()方法比较的是字符串的内容,而==运算符比较的是字符串对象的引用。

4. 不可变哈希值:String类中的哈希值是不可变的,一旦计算出来就不能被修改。这种不可变性使得String对象可以作为Map的key来使用。

5. 字符串操作方法:String类中提供了多种字符串操作方法,如substring()、trim()、toUpperCase()、toLowerCase()等,可以方便地对字符串进行操作和处理。

6. 国际化支持:String类中提供了多种支持国际化的方法,如getBytes()、charAt()、length()等,可以处理不同语言和编码的字符串。

String为什么是不可变的吗?

String是不可变的,主要是为了保证程序的安全性和性能。

1. 安全性:如果String是可变的,那么在多线程环境下,多个线程可能会同时修改同一个String对象,从而导致数据不一致的问题。为了避免这种问题,Java将String设计为不可变的,一旦创建,就不能被修改,这样就可以避免多线程环境下的数据竞争问题。

2. 性能:如果String是可变的,那么每次修改字符串都需要创建一个新的String对象,这样会导致频繁的对象创建和销毁,从而降低程序的性能。为了避免这种问题,Java将String设计为不可变的,一旦创建,就不需要再修改,这样可以避免频繁的对象创建和销毁,提高程序的性能。

另外,String是不可变的还有一个好处,就是可以作为Map的key来使用。由于String的哈希值是不可变的,一旦计算出来就不能被修改,所以String对象可以作为Map的key来使用,保证了Map的稳定性和正确性。如果String是可变的,就不能作为Map的key来使用,从而限制了Map的使用范围。

综上所述,String是不可变的,主要是为了保证程序的安全性和性能。

是否可以继承 String 类 

String 类是 final 类,不可以被继承。

String str="i"与 String str=new String(“i”)一样吗? 

在功能上,String str="i"与String str=new String("i")是相同的,都是创建一个包含单个字符i的字符串对象。但是,在内存中,它们是不同的。

String str="i"是使用字符串常量池中的字符串常量创建的,而字符串常量池是Java中的一种特殊的内存区域,用于缓存字符串常量,以便重复使用。当程序创建一个字符串常量时,如果该字符串常量在常量池中已经存在,则直接返回该字符串常量的引用;如果该字符串常量在常量池中不存在,则将该字符串常量添加到常量池中,并返回该字符串常量的引用。因此,使用String str="i"创建的字符串对象会被添加到字符串常量池中,如果创建多个包含相同内容的字符串对象,只会在字符串常量池中创建一个对象,可以节省内存空间。

而String str=new String("i")是使用new关键字创建的字符串对象,每次都会在堆内存中创建一个新的对象,不会使用字符串常量池中的对象。如果创建多个包含相同内容的字符串对象,每个对象都会在堆内存中创建一个新的对象,会占用更多的内存空间。

因此,如果需要创建包含单个字符的字符串对象,建议使用String str="i"的方式,可以避免在堆内存中创建多个相同的对象,节省内存空间。

String s = new String(“xyz”);创建了几个字符串对象

使用String s = new String("xyz")创建了两个字符串对象。

第一个字符串对象是字面量"xyz",它是在编译期间就被创建并存储在字符串常量池中的。当程序执行到String s = new String("xyz")这句话时,会在堆内存中创建一个新的String对象,该对象的内容是字符串常量池中"xyz"字符串对象的拷贝。因此,使用new关键字创建String对象时,会在堆内存中创建一个新的对象。

总之,使用String s = new String("xyz")创建了两个字符串对象,一个是字符串常量池中的"xyz"字符串对象,另一个是堆内存中的新对象,该对象的内容是字符串常量池中"xyz"字符串对象的拷贝。需要注意的是,如果在代码中多次使用相同的字符串字面量,只会在字符串常量池中创建一个字符串对象,不会重复创建。

String str1 ="hello";//str1指向静态区(字符串常量池)

String str2 =new String("hello");//str2指向堆上的对象

String str3 ="hello";

String str4=new String("hello");

1、System.out.println(str1.equals(str2));//true

2、System.out.println(str2.equals(str4));//true

3、System.out.println(str1== str3);//true

4、System.out.println(str1 == str2);//false

5、System.out.println(str2 == str4);//false

6、System.out.println(str2=="hello");//false

str2 = str1;

7、System.out.println(str2 =="hello");//true

骚戴理解:首先String的equals方法是被重写过的,比较的内容是否相同,所以序号1和2都是true,因为内容都是hello,但是"=="在比较引用类型的时候比较的是内存地址是否相同,因为str1和str3都是指向的字符串常量池里hello这个字符串的地址,所以序号3位true,但是序号4、5、6都是false,因为它们内存地址都不一样,str2 = str1把str2指向的地址改成了指向字符串常量池中hello的地址后自然序号7为true

如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

示例代码:

// StringBuffer reverse

StringBuffer stringBuffer = new StringBuffer();

stringBuffer. append("abcdefg");

System. out. println(stringBuffer. reverse());

结果: gfedcba

// StringBuilder reverse

StringBuilder stringBuilder = new StringBuilder();

stringBuilder. append("abcdefg");

System. out. println(stringBuilder. reverse());

结果: gfedcba

数组有没有 length()方法?String 有没有 length()方法

数组没有length()方法,但是有一个length属性,可以用来获取数组的长度,或者用 size方法。

例如,对于int类型的数组,可以使用以下方式获取数组的长度:

int[] arr = {1, 2, 3, 4, 5};
int len = arr.length; // 获取数组的长度,结果为5

对于String类型的对象,有一个length()方法,可以返回字符串的长度,即字符串中字符的个数。

例如,可以使用以下方式获取字符串的长度:

String str = "Hello World";
int len = str.length(); // 获取字符串的长度,结果为11

需要注意的是,String的length()方法返回的是字符串中字符的个数,而不是字节数或者编码单元数。对于包含Unicode字符的字符串,其长度可能会大于字符串的字节数或编码单元数。

String 类的常用方法都有那些? 

String类是Java中最常用的类之一,提供了许多实用的方法,下面列出了String类的一些常用方法:

1. charAt(int index):返回指定索引处的字符。

2. length():返回字符串的长度,即字符串中字符的个数。

3. substring(int beginIndex):返回从指定索引开始到字符串末尾的子字符串。

4. substring(int beginIndex, int endIndex):返回从指定索引开始到指定索引结束的子字符串。

5. equals(Object obj):比较字符串是否相等,区分大小写。

6. equalsIgnoreCase(String anotherString):比较字符串是否相等,忽略大小写。

7. compareTo(String anotherString):按字典顺序比较两个字符串,如果相等返回0,如果当前字符串大于另一个字符串返回正数,否则返回负数。

8. toLowerCase():将字符串中的所有字符转换为小写。

9. toUpperCase():将字符串中的所有字符转换为大写。

10. trim():去除字符串开头和结尾的空格。

11. startsWith(String prefix):判断字符串是否以指定的前缀开始。

12. endsWith(String suffix):判断字符串是否以指定的后缀结束。

13. indexOf(int ch):返回指定字符在字符串中第一次出现的索引。

14. lastIndexOf(int ch):返回指定字符在字符串中最后一次出现的索引。

15. replace(char oldChar, char newChar):将字符串中的所有旧字符替换为新字符。

16. replaceAll(String regex, String replacement):将字符串中所有匹配正则表达式的子串替换为指定字符串。

17. split(String regex):按照指定的正则表达式将字符串拆分为多个子串。

18. valueOf(Object obj):将指定的对象转换为字符串。

19. format(String format, Object... args):使用指定的格式字符串和参数返回格式化的字符串。

在使用 HashMap 的时候,用 String 做 key 有什么好处? 

在使用HashMap时,使用String作为key有以下好处:

1. String是不可变的,因此可以保证key的不可变性,避免了在修改key时可能出现的问题。

2. String的hashCode()方法被重写过,可以保证相同字符串的hashCode值相同,因此可以更好地利用HashMap的散列特性。

3. String实现了Comparable接口,可以进行比较,因此在对HashMap进行排序或者遍历时,可以更方便地进行操作。

4. String是Java中最常用的类之一,使用String作为key可以提高代码的可读性和可维护性。

骚戴理解:需要注意的是,在使用自定义类作为HashMap的key时,需要重写hashCode()和equals()方法,以保证正确性和性能。

String和StringBuffer、StringBuilder的区别是什么? 

String、StringBuffer和StringBuilder都是Java中用于处理字符串的类,它们的主要区别如下:

1. String是不可变的,即一旦创建就不能修改,对String对象进行修改实际上是创建了一个新的String对象,旧的String对象仍然存在。而StringBuffer和StringBuilder是可变的,可以修改其内容。

2. StringBuffer和StringBuilder都是可变的字符串缓冲区,它们的主要区别在于线程安全性。StringBuffer是线程安全的,即多个线程可以同时访问一个StringBuffer对象并执行修改操作,而不会产生不一致的结果。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder则是非线程安全的,如果多个线程同时访问一个StringBuilder对象并执行修改操作,可能会产生不一致的结果。String中的对象是不可变的,也就可以理解为常量,线程安全。

3. 在字符串拼接的场景中,如果使用String进行拼接,每次拼接都会创建一个新的String对象,如果拼接的字符串比较多,会产生大量的临时对象,占用大量内存,影响性能。而如果使用StringBuffer或StringBuilder进行拼接,由于它们是可变的,可以直接在原有对象上进行修改,避免了创建大量临时对象,提高了性能。

 骚戴理解:性能由好到坏:StringBuilder>StringBuffer>String

总之,String、StringBuffer和StringBuilder都有各自的特点,需要根据具体的场景选择合适的类进行使用。如果需要进行频繁的字符串拼接操作,建议使用StringBuffer或StringBuilder,而不是使用String。如果需要在多线程环境下进行字符串操作,建议使用StringBuffer,而不是使用StringBuilder。

包装类

自动装箱与拆箱

装箱:将基本类型用它们对应的引用类型包装起来;

拆箱:将包装类型转换为基本数据类型;

int 和 Integer 有什么区别 

它们的主要区别如下:

1. int是Java的基本数据类型,而Integer是int的包装类,是一个对象。

2. int在内存中占用4个字节,而Integer对象在内存中占用更多的空间。

3. int可以直接进行数值运算,而Integer对象需要通过intValue()方法将其转换为int类型后才能进行数值运算。

4. int是值类型,即在传递时传递的是实际的数值,而Integer是引用类型,即在传递时传递的是对象的引用。

5. 在使用时,int通常用于基本的数值运算,而Integer通常用于需要将int类型的数据封装成对象的场景,例如在集合类中存储int类型的数据。

总之,int和Integer都有各自的特点和使用场景,需要根据具体的需求进行选择和使用。需要注意的是,在进行数值运算时,尽量使用int,避免使用Integer对象,以提高性能。

 Java 原始类型和包装类对比

Java 为每个原始类型提供了包装类型:

原始类型::boolean char byte short int long float double

包装类型:Boolean Character Byte Short Integer Long Float Double

Integer a= 127 与 Integer b = 127相等吗

相等

总结

  • int 和Integer在进行比较的时候,Integer会进行拆箱,转为int值与int进行比较。
  • Integer与Integer比较的时候,由于直接赋值的时候会进行自动的装箱,那么这里就需要注意两个问题
  1. 一是-128<= x<=127的整数,那么当赋值在这个区间的时候,不会创建新的Integer对象,而是从IntegerCache缓存中获取已经创建好的Integer对象。
  2. 二是当大于这个范围的时候,直接new Integer来创建Integer对象。
  • new Integer(1) 和Integer a = 1不同,前者会创建对象,存储在堆中,而后者因为在-128到127的范围内,不会创建新的对象,而是从IntegerCache中获取的。那么Integer a = 128, 大于该范围的话才会直接通过new Integer(128)创建对象,进行装箱。
  • 对于对象引用类型:==比较的是对象的内存地址。对于基本数据类型:==比较的是值。
  • 注意只有new Integer不一样点,不管new的这个数是不是在-128到127这个范围内都会在堆中创建一个新的对象,而不是使用IntegerCache缓存中的值
public class a {
    public static void main(String[] args){
        Integer a =new Integer(3); 
        Integer b =3;// 将 3 自 动 装 箱 成 Integer 类 型
        int c =3;
        System.out.println(a == b);// false 两个引用没有引用同一对象
        System.out.println(a == c);// true a自动拆箱成int类型再和c比较
        System.out.println(b == c);// true
    }
}

骚戴理解:Integer a =new Integer(3);是创一个对象在堆里, Integer b =3;是直接从IntegerCache缓存中拿(-128到127这个范围内的Integer对象已经在这个IntegerCache缓存中创建好了的),把b的引用指向IntegerCache缓存中的3。所以第一个判断为false。

第二个和第三个都是因为会拆箱,所以就是int之间的值比较,自然是true

package anomyous;

public class Test {


    public static void main(String[] args) {
        Integer i1=new Integer(99);
        Integer i2=Integer.valueOf(99);//手动装箱
        Integer i3=99;//自动装箱 隐式调用Integer.valueOf()

        System.out.println(i1==i2);//false
        System.out.println(i2==i3);//true  
        System.out.println(i1==i3);//false

    }
}
public static void main(String[] args){
    Integer a1 =128; 
    Integer b1 =128; 
    System.out.println(a1 == b1);// false 
    Integer a2=127;   
    Integer b2 =127;    
    System.out.println(a2 == b2);// true
} 

骚戴理解:如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer对象,超过范围 a1==b1的结果是false

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/685430.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring相关API

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;JavaEE、Spring SpringAPI 1、继承体系2、 getBean() 1、继承体系 上述继承体系中的主要类和接口包括&#xff1…

WebRTC-STUN协议详解

1、STUN协议概述 STUN&#xff08;Session Traversal Utilities for NAT&#xff09;NAT会话穿透工具&#xff0c;STUN是一个Client/Server协议&#xff0c;支持请求/响应类型、指示类型两种类型。STUN作为ICE&#xff08;Interactive Connectivity Establishment&#xff0c;…

【需求实现】输入多少就输出多少的拟合任务如何实现(一):数据集分割

神经网络中输入多少数据就输出多少数据的情况如何实现 导读数据集长什么样&#xff1f;怎么分割数据集&#xff1f;时间窗口分析模板我知道你很急&#xff0c;但你先别急 换个思路 导读 在实习的过程中遇到了这样一种需求&#xff1a;给定一条序列&#xff0c;并另外给定一条期…

使用ffmpeg将rtsp流转流实现h5端播放

主要实现rtsp转tcp协议视频流播放 ffmpeg下载安装&#xff08;公认业界视频处理大佬&#xff09; a、官网地址&#xff1a;www.ffmpeg.org/ b、gitHub&#xff1a;github.com/FFmpeg/FFmp… c、推荐下载地址&#xff1a;ffmpeg.zeranoe.com/builds/ (选择如下图) 2.配置ffmpeg…

期末复习【计算机系统结构】

期末复习【计算机系统结构】 前言推荐押题公式 期末复习重点第1章 计算机体系结构的基本概念1.3 定量分析技术1.3.1计算机系统设计的定量原理 第2章 计算机指令集结构第3章 流水线技术3.2 流水线的性能指标3.2.1 吞吐率3.2.2 加速比3.2.3 效率3.2.4 流水线性能分析举例 3.3 流水…

miniconda的安装

1. conda 是一个开源的包、环境管理器&#xff0c;可以用于在同一个机器上安装不同版本的软件包及其依赖&#xff0c;并能够在不同的环境之间切换。 miniconda官网下载 miniconda清华镜像下载 找到自己想要安装的版本&#xff0c;我这里选择的是Miniconda3-4.7.12.1-Linux-x…

OUC编译原理实验报告 实验4:验证Yacc的使用/实验e4:从语言SUM到栈式计算机STACK的机器语言的翻译

编译原理实验报告 实验4&#xff1a;验证Yacc的使用 实验e4&#xff1a;从语言SUM到栈式计算机STACK的机器语言的翻译 中国海洋大学编译原理实验2023春 仅供同学参考思路 请勿直接抄袭 否则可能喜提0分 目录 文章目录 编译原理实验报告目录一.实验目的二.实验内容实验4实验…

多进程爬虫实战-摩托车网

前言 最近有遇到很多私信让我讲一讲多进程的爬虫&#xff0c;我发现大家对爬虫的框架写法和进程的理解有很多的问题和疑问&#xff0c;这次就带来一个小实战让大家理解多进程爬虫以及框架的写法 由于进程爬虫会对任何服务器都有一定的影响&#xff0c;本文仅供学习交流使用&…

【Linux后端服务器开发】C程序预处理

目录 一、源文件到可执行程序的过程 二、预定义符号 三、#define宏定义 四、条件编译 一、源文件到可执行程序的过程 预处理&#xff1a;去注释&#xff0c;宏替换&#xff0c;头文件展开&#xff0c;条件编译编译&#xff1a;c语言 ---> 汇编语言&#xff08;语法分析…

JUC高级-0625

13. AbstractQueuedSynchronized之AQS 13.1 前置知识 公平锁和非公平锁可重入锁自旋思想LockSupport数据结构之双向链表设计模式之模板设计模式 13.2 AQS入门级别理论知识 AQS是什么&#xff1f; 字面意思&#xff1a;抽象的队列同步器&#xff0c;实现了通知唤醒的机制源代…

8通道250MSPS采样率16位AD采集FMC子卡-高速数据采集专家

FMC128是一款8通道250MHz采样率16位分辨率AD采集FMC子卡&#xff0c;符合VITA57.1规范&#xff0c;可以作为一个理想的IO模块耦合至FPGA前端&#xff0c;8通道AD将模拟信号数字化后通过高带宽的FMC连接器&#xff08;HPC&#xff09;连接至FPGA&#xff0c;从而大大降低了系统信…

电力智能运维是什么?有哪些优势?

设备检修维护是指对设备和系统进行必要的监视、维修和养护&#xff0c;通过日常的维护使设备保持良好的状态&#xff0c;确保设备安全、稳定、经济运行。由于时代的变迁&#xff0c;电力设备的检测维修变得也越来越智能化。采用的智能运维系统&#xff0c;可以更好的监控电力设…

BCSP-玄子Java开发之Java Web编程CH01_初识动态网页

BCSP-玄子Java开发之Java Web编程CH01_初识动态网页 1.1 B/S架构 B/S架构&#xff1a;浏览器/服务器 程序完全部署在服务器上使用浏览器访问服务器无需单独安装客户端软件 为什么要使用B/S架构 B/S与C/S比较B/S架构C/S架构软件安装浏览器需要专门的客户端应用升级维护客户…

NGINX PHP Cookie 会话中 PHPSESSID 缺少 HTTPOnly、Secure 属性解决方案

NGINX & PHP Cookie 会话中 PHPSESSID 缺少 HTTPOnly、Secure 属性解决方案 1 / 说明 基于安全的考虑&#xff0c;需要给cookie加上Secure和HttpOnly属性&#xff0c;HttpOnly比较好理解&#xff0c;设置HttpOnlytrue的cookie不能被js获取到&#xff0c;无法用document.coo…

linux系统的文件等相关操作命令

文章目录 1 查找文件&#xff08;find、grep&#xff09;2 查看文件内容&#xff08;cat、more、less、head、tail&#xff09;3 文件比较&#xff08;diff&#xff09;4 文本编辑器&#xff08;vi、vim&#xff09;5 文件压缩与解压&#xff08;tar、tar.tgz、zip、rar、rar.g…

yum安装 lnmp

目录 一.nginx 的yum安装 1.关闭防火墙 2. 安装 nginx 3.安装依赖包 4.启动服务 二. 安装 mysql 5.7 (mariadb) 1.nysal的yum安装 2. 启动服务 3.在日志文件中找出root用户的初始密码 4.登录 mysql 5. 停止版本更新&#xff0c;稳定数据库的运行 三.php 的yum安装 1.…

rust abc(4): 定义变量并使用 mut 关键字

文章目录 1. 目的2. 不可变变量 (immutable variable)2.1 含义2.2 代码实例 3. 可变变量 (mutable variable)3.1 含义3.2 代码实例 4. 总结 1. 目的 学习 rust 语言中变量的定义方式&#xff0c; 包括普通变量&#xff08;immutable&#xff09;、可变变量&#xff08;mutable…

轻量云服务器(香港)ping不通怎么解决?

​  在使用轻量云服务器(香港)时&#xff0c;有时候会出现ping不通的情况&#xff0c;这时候我们该怎么办呢? 首先&#xff0c;我们需要知道 ping 不通的原因。 ping 是一种基于 ICMP 协议的网络测试工具&#xff0c;它可以用来测试网络连接的质量和速度。如果 ping 不通&am…

英特尔进军晶圆代工,台积电“危”?

近来&#xff0c;半导体市场再次变得繁荣&#xff0c;尤其随着AI大型机模型的出现&#xff0c;半导体巨头们纷纷加大投资力度&#xff0c;以期在AI时代中积蓄新的增长。 作为AI大模型时代中最受益的厂商之一&#xff0c;英伟达稳居市场前沿&#xff0c;而AMD也加入了竞争&…

阿里发布2023年Java社招岗(正式版)面试题

每年的金三银四、金九银十都是各大公司招聘程序员的最佳时期&#xff0c;在这段时间内有好多程序员为面试而发愁&#xff0c;不知道如何才能收到好的 offer&#xff0c;拿到理想的薪资&#xff0c;实现自我的人生价值&#xff01; 我想告诉大家的是&#xff0c;其实都不用愁的…