谈谈你对 Java SE、Java EE、Java ME 的理解
我个人理解 Java SE 就是 Java 的标准版,是整个 Java 的基础和核心,包括Java基础语法、基本数据结构、常见的 API等,是 Java EE的基础。
Java EE 则是在 Java SE 的基础上构建的,是针对企业应用程序的扩展版本,提供许多专门的API和开发工具,例如用于Web服务的JAX-WS、用于消息队列的JMS、用于事务的JTA、用于持久化的JPA等等。
说一说 JDK、JRE 和 JVM的区别
JDK(Java SE Development kit):Java标准开发包,它提供了编译、运行 Java程序所需的各种工具和资源,包括 Java编译器(javac)、JRE,以及常用的Java类库等。
JRE(Java Runtime Envelopment):Java运行时环境,用于运行Java字节码文件,包括JVM以及JVM工作所需的类库。
JVM(Java virtual machine):Java虚拟机,是JRE的一部分,是Java实现跨平台最核心的部分,主要负责运行字节码文件。
Java 运行 jar包的相关命令
//当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出
java -jar app.jar
//&代表在后台运行
//当前ssh窗口不被锁定,但是当窗口关闭时,程序中止运行。
java -jar app.jar &
使用命令运行一个java文件
1.编译 HelloWorld.java文件
javac HelloWorld.java
编译后会生成对应的字节码文件( HelloWorld.class)
2.运行字节码文件
java HelloWorld
HelloWorld.java如下:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("HelloWorld");
}
}
面向对象的特性(追问多态,说回答得太官方了)
封装: 封装从字面上来理解就是包装的意思,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,只保留一些对外接口使之与外部发生联系。
继承: 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。
关于继承如下 3 点请记住:
-
子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
-
子类可以拥有自己属性和方法,即子类可以对父类进行扩展。
-
子类可以用自己的方式实现父类的方法。(以后介绍)
多态性: 它是指在父类中定义的属性和方法被子类继承之后,可以具有不同的数据类型或表现出不同的行为,这使得同一个属性或方法在父类及其各个子类中具有不同的含义。
Java实现多态有三个必要条件:继承、重写、向上转型。
继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能既可以调用父类的方法,又能调用子类的方法。
只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
翻译成人话:
如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法
重载(Overload)和重写(Override)的区别是什么?
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性(静态多态),而后者实现的是运行时的多态性(动态多态)。
重载
发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。
重写
重写发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。
-
方法名、参数列表必须相同,子类方法返回值类型应比父类方法返回值类型更小或相等,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
-
如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。
-
构造方法无法被重写。
构造器(constructor)是否可被重写(override)?
构造器不能被继承,因此不能被重写,但可以被重载。每一个类必须有自己的构造函数,负责构造自己这部分的构造。子类不会覆盖父类的构造函数,相反必须一开始调用父类的构造函数。
java中有几种循环
for循环
for (初始化语句;条件判断语句;条件控制语句) {
循环体语句;
}
-
初始化语句: 用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样
-
条件判断语句:用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去
-
循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情
-
条件控制语句:用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去
执行流程:
-
执行初始化语句
-
执行条件判断语句,看其结果是true还是false
- 如果是false,循环结束
- 如果是true,继续执行
-
执行循环体语句
-
执行条件控制语句
-
回到2继续
while循环
初始化语句;
while (条件判断语句) {
循环体语句;
条件控制语句;
}
执行流程:
-
执行初始化语句
-
执行条件判断语句,看其结果是true还是false
- 如果是false,循环结束
- 如果是true,继续执行
-
执行循环体语句
-
执行条件控制语句
-
回到2继续
dowhile循环
初始化语句;
do {
循环体语句;
条件控制语句;
}while(条件判断语句);
执行流程:
-
执行初始化语句
-
执行循环体语句
-
执行条件控制语句
-
执行条件判断语句,看其结果是true还是false
- 如果是false,循环结束
- 如果是true,继续执行
- 回到2继续
三种循环的区别
- 三种循环的区别
-
for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
-
do…while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
- for循环和while的区别
-
条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
-
条件控制语句所控制的自增变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用
- 死循环(无限循环)的三种格式:
- for(; ; ){}
- while(true){}
- do {} while(true);
stream流用过吗?它能够实现什么?
stream流并不存储数据,主要用来检索和逻辑处理集合数据,包括筛选、排序、统计、计数等。、
stream怎么实现循环?stream循环我们怎么来引用的?
详细介绍,可以参考这篇文章——Java进阶—Stream流、方法引用。
讲讲对lambda表达式的理解
Lambda表达式是一种匿名函数,可以把Lambda表达式理解为是一段可以传递的代码,使用 Lambda 表达式可以使代码变的更加简洁紧凑,让 Java 也能支持简单的函数式编程。
Lambda表达式的语法格式通常是使用关键字lambda,后面跟着一组参数,然后再接一个冒号和一个表达式,这个表达式就是这个匿名函数要执行的代码块。Lambda表达式的执行结果就是这个代码块的返回值。
Lambda表达式通常用在需要传递函数对象的场合,比如作为参数传递给某个函数,或者作为某个数据结构中的元素。它可以帮助我们避免定义一些简单的函数,从而让代码更加简洁、易读和可维护。
函数式编程是什么
函数式编程是一种编程范式,其核心思想是将计算过程看作是一系列函数的应用。在函数式编程中,函数被看作是一等公民,也就是说,它们可以像其他值一样被传递、存储和操作。函数式编程通常使用纯函数,也就是没有副作用、不依赖于外部状态、只根据输入计算输出的函数。此外,函数式编程也强调不可变性,即数据在创建后不能被修改,而是通过创建新的数据来实现状态变化。函数式编程的另一个特点是高阶函数,即可以接受函数作为参数或返回函数的函数。函数式编程可以帮助开发者编写更加简洁、可读性更强、更加健壮的代码,也有利于并行和异步计算。
函数式编程的本质是:把函数看作是数据。