Java线程Java类垃圾收集器面向对象编程(OOP)

代码重用。增强代码的可靠性和灵活性。增加代码的可理解性。面向对象编程有许多重要的特性,如:封装、继承、多态和抽象。 在接下来的章节中我们将一一分析这些特性。Java线程Java类垃圾收集器面向对象编程(OOP)

java数组长度函数_数组长度函数c语言_数组长度的函数java

封装为对象提供了隐藏内部属性和行为的能力。 对象提供可供其他对象访问以更改其内部数据的方法。 在Java中,有3种修饰符:public、private和protected。 每个修饰符赋予同一包或不同包下的其他对象不同的访问权限。

下面列出了使用封装的一些好处:

通过隐藏对象的属性来保护对象内部的状态。

提高代码的可用性和可维护性,因为对象的行为可以单独更改或扩展。

禁止对象之间的不良交互可以提高模块化程度。

有关封装的更多详细信息和示例,请参阅此文档。

多态性

多态性是编程语言为不同的底层数据类型显示相同接口的能力。 对多态类型的操作可以应用于其他类型的值。

继承

继承使对象能够从基类获取字段和方法。 继承提供了代码重用以及在不修改类的情况下向现有类添加新功能的能力。

抽象的

抽象是将想法与具体实例分离的步骤,因此类是根据其功能而不是实现细节创建的。 Java 支持创建仅公开接口但不公开方法实现的抽象类。 这种抽象技术的主要目的是将类的行为与其实现细节分开。

抽象和封装之间的区别

抽象和封装是互补的概念。 一方面,抽象关注对象的行为。 另一方面,封装关注对象行为的细节。 通常,封装是通过隐藏对象的内部状态信息来实现的。 因此,封装可以被视为一种提供抽象的策略。

数组长度函数c语言_java数组长度函数_数组长度的函数java

常见 Java 问题

1.什么是Java虚拟机? 为什么Java被称为“平台无关的编程语言”?

Java虚拟机是一个可以执行Java字节码的虚拟机进程。 Java源文件被编译成可由Java虚拟机执行的字节码文件。

Java 的设计目的是允许应用程序在任何平台上运行,而不需要程序员为每个平台单独重写或重新编译。 Java 虚拟机使这成为可能,因为它知道底层硬件平台的指令长度和其他特征。

2.JDK和JRE有什么区别?

Java 运行时环境 (JRE) 是执行 Java 程序的 Java 虚拟机。 它还包含执行小程序所需的浏览器插件。 Java开发工具包(JDK)是一个完整的Java软件开发工具包,包括JRE、编译器和其他工具(如:JavaDoc、Java调试器),它允许开发人员开发、编译和执行Java应用程序。

3.“static”关键字是什么意思? Java 中私有或静态方法可以被重写吗?

“static”关键字表示成员变量或成员方法无需所属类的实例变量即可访问。

Java中的静态方法不能被重写,因为方法重写是基于运行时动态绑定的,而静态方法是在编译时静态绑定的。 静态方法不与类的任何实例关联,因此它在概念上不适用。

4. 静态环境下是否可以访问非静态变量?

静态变量属于Java中的一个类,并且它的值在所有实例中都是相同的。 当Java虚拟机加载一个类时,静态变量会被初始化。 如果您的代码尝试在没有实例的情况下访问非静态变量,编译器将报告错误,因为这些变量尚未创建并与任何实例关联。

5. Java支持哪些数据类型? 什么是自动拆箱?

Java语言支持的8种基本数据类型是:

字节

短的

整数

长的

漂浮

双倍的

布尔值

字符

自动装箱是 Java 编译器在原始数据类型和相应的对象包装类型之间完成的转换。 例如:将int转换为Integer,将double转换为double等。 相反的是自动拆箱。

6、Java中方法重写(Overriding)和方法重载(Overloading)是什么意思?

Java 中的方法重载是指同一个类中的两个或多个方法具有相同的方法名但参数不同的情况。 相反,方法重写是指子类重新定义父类的方法。 方法重写必须具有相同的方法名称、参数列表和返回类型。 重写者不能限制对其重写的方法的访问。

7. Java中什么是构造函数? 什么是构造函数重载? 什么是复制构造函数?

创建新对象时会调用构造函数。 每个类都有一个构造函数。 在程序员没有为类提供构造函数的情况下,Java编译器将为该类创建一个默认构造函数。

Java 中的构造函数重载与方法重载非常相似。 一个类可以创建多个构造函数。 每个构造函数必须有自己的参数列表。

Java 不像 C++ 那样支持复制构造函数,不同之处在于,如果您不编写自己的构造函数,Java 不会创建默认的复制构造函数。

8. Java支持多重继承吗?

不,Java 不支持多重继承。 每个类只能继承一个类,但可以实现多个接口。

9. 接口和抽象类有什么区别?

Java 提供并支持抽象类和接口的创建。 他们的实现有一些共同点,不同的是:

接口中的所有方法都是隐式抽象的。 抽象类可以包含抽象方法和非抽象方法。

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

如果一个类实现了一个接口,则它必须实现该接口声明的所有方法。 但是,类可能无法实现抽象类声明的所有方法。 当然,在这种情况下,该类也必须声明为抽象类。

抽象类可以实现接口而不提供接口方法的实现。

Java接口中声明的变量默认是final的。 抽象类可以包含非终变量。

Java 接口中的成员函数默认是公共的。 抽象类的成员函数可以是私有的、受保护的或公共的。

接口是抽象的,无法实例化。 抽象类也不能被实例化,但如果它包含 main 方法则可以被调用。

也可以参考JDK8中抽象类和接口的区别

10. 什么是值传递和引用传递?

对象按值传递,这意味着传递对象的副本。 因此,即使对象副本发生变化,也不会影响源对象的值。

对象是通过引用传递的,这意味着传递的不是实际的对象,而是对该对象的引用。 因此,对引用对象的外部更改将反映在所有对象中。

java线程

11.进程和线程有什么区别?

进程是正在执行的应用程序,线程是进程内的执行序列。 一个进程可以有多个线程。 线程也称为轻量级进程。

12. 创建线程有多少种不同的方式? 你喜欢哪一个? 为什么?

创建线程有以下三种方式:

继承Thread类

实现Runnable接口

应用程序可以使用Executor框架创建线程池

更流行的是实现Runnable接口,因为它不需要继承Thread类。 在应用设计中已经继承了其他对象的情况下,这需要多重继承(而Java不支持多重继承),只能实现接口。 同时,线程池也非常高效且易于实现和使用。

数组长度的函数java_java数组长度函数_数组长度函数c语言

13. 一般解释线程的几种可用状态。

在执行过程中,线程可以处于以下状态:

绪(Runnable):线程已准备好运行,但可能不会立即开始执行。

运行:进程正在执行线程的代码。

等待(Waiting):线程处于阻塞状态,等待外部处理结束。

睡眠:线程被迫睡眠。

I/O 阻塞(Blocked on I/O):等待 I/O 操作完成。

同步时阻塞:等待获取锁。

Dead:线程已完成执行。

14.步方法和同步代码块有什么区别?

在Java语言中,每个对象都有一个锁。 线程可以使用synchronized关键字来获取对象的锁。 Synchronized关键字可以应用于方法级别(粗粒度锁)或代码块级别(细粒度锁)。

15、Monitor内部如何进行线程同步? 程序应该执行什么级别的同步?

监视器和锁在Java虚拟机中一起使用。 监视器监视同步代码块,以确保一次只有一个线程执行同步代码块。 每个监视器都与一个对象引用相关联。 在获取锁之前,不允许线程执行同步代码。

16.什么是死锁?

当两个进程都在等待对方完成执行然后再继续执行时,会发生死锁。 结果是两个进程都陷入无限等待。

17、如何保证N个线程可以访问N个资源而不造成死锁?

使用多线程时,一个很简单的避免死锁的方法是:指定获取锁的顺序,强制线程按照指定的顺序获取锁。 因此,如果所有线程以相同的顺序获取和释放锁,不会出现死锁。

Java类

18、Java类框架有哪些基本接口?

Java类提供了一组设计良好的接口和类,支持对一组对象的操作。 Java类中基本的接口有:

Collection:代表一组对象,每个对象都是其子元素。

Set:不包含重复元素的。

列表:可以包含重复元素的顺序。

Map:可以将键(key)映射到值(value)的对象,并且键不能重复。

19.为什么类没有实现Cloneable和Serialized接口?

类接口指定了一组称为元素的对象。 接口的每个具体实现都可以选择以自己的方式存储和排序元素。 有些类允许重复键,有些则不允许。

20.什么是迭代器?

Iterator接口提供了许多用于迭代元素的方法。每个类都包含一个返回迭代器实例的类

迭代法。 迭代器可以在迭代期间删除底层的元素。

克隆或序列化的语义和含义是特定于实现的。 因此,应该由类的具体实现来决定如何克隆或序列化。

21.Iterator和ListIterator有什么区别?

它们的区别如下:

Iterator可以用来遍历Set和List,但是ListIterator只能用来遍历List。

Iterator只能向前遍历,而ListIterator可以向前也可以向后遍历。

ListIterator实现了Iterator接口并包含其他功能,例如:添加元素、替换元素、获取上一个和下一个元素的索引等等。

22. 快速失败和自动失败有什么区别?

迭代器的故障保护基于创建底层的副本,因此它不会受到源修改的影响。 java.util 包下的所有类都是快速失败的,而 java.util.concurrent 包下的所有类都是失败安全的。 快速失败迭代器将抛出 ConcurrentModificationException,而故障安全迭代器永远不会抛出此类异常。

23、Java中HashMap的工作原理是什么?

Java中的HashMap以键值对的形式存储元素。 HashMap 需要一个哈希函数,该函数使用 hashCode() 和 equals() 方法向添加元素或从中检索元素。 当调用 put() 方法时,HashMap 会计算键的哈希值,然后将键值对存储在中适当的索引处。 如果键已经存在,则值将更新为新值。 HashMap 的一些重要特性是其容量、负载因子和阈值调整。

24. hashCode() 和 equals() 方法的重要性是什么?

Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,并且在根据键获取值时也会使用这两个方法。 如果这两种方法没有正确实现,两个不同的键可能具有相同的哈希值,因此,可能会被认为是相等的。 而且,这两种方法也用于查找重复元素。 因此,这两种方法的实现对于HashMap的准确性和正确性至关重要。

25.HashMap和Hashtable有什么区别?

HashMap和Hashtable都实现了Map接口,因此很多功能非常相似。 但是,它们在以下方面有所不同:

HashMap允许键和值为空,而Hashtable不允许键或值为空。

Hashtable 是同步的,而 HashMap 不是。 因此,HashMap更适合单线程环境,而Hashtable适合多线程环境。

HashMap提供了应用程序可以迭代的键的,因此,HashMap是快速失败的。 另一方面,Hashtable提供了键的枚举(Enumeration)。

Hashtable 通常被认为是一个遗留类。

26.数组(Array)和列表(ArrayList)有什么区别? 什么时候应该使用Array而不是ArrayList?

Array 和 ArrayList 的区别如下:

Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。

Array的大小是固定的,ArrayList的大小是动态的。

ArrayList提供了更多的方法和特性,如:addAll()、removeAll()、iterator()等。

对于原始类型,使用自动装箱来减少编码工作。 然而,在处理固定大小的原始数据类型时,这种方法相对较慢。

27.ArrayList和LinkedList有什么区别?

ArrayList和LinkedList都实现了List接口,它们有以下区别:

ArrayList是一个基于索引的数据接口,其底层是数组。 它可以以 O(1) 的时间复杂度对元素进行随机访问。 相应地,LinkedList 以元素列表的形式存储其数据,每个元素都与其上一个和下一个元素链接。 在这种情况下,查找元素的时间复杂度为O(n)。

与ArrayList相比,LinkedList的插入、添加和删除操作速度更快,因为当向中的任意位置添加元素时,不需要像数组那样重新计算大小或更新索引。

LinkedList比ArrayList占用更多内存,因为LinkedList为每个节点存储两个引用,一个指向前一个元素,一个指向下一个元素。

另请参见 ArrayList 与 LinkedList。

Comparable 和 Comparator 接口的用途是什么? 列出他们的差异。

Java提供了Comparable接口,它只包含一个compareTo()方法。 该方法可以同时对两个对象进行排序。 具体来说,它返回负数、0 和正数来指示输入对象小于、等于或大于现有对象。

Java 提供了 Comparator 接口,其中包含两个方法:compare() 和 equals()。 Compare()方法用于对两个输入参数进行排序,返回一个负数0,一个正数表示个参数小于、等于或大于第二个参数。 equals()方法以一个对象作为参数,用于判断输入参数是否等于比较器。 仅当输入参数也是比较器并且输入参数和当前比较器的排序结果相同时,此方法才返回 true。

什么是Java优先级队列(PriorityQueue)?

PriorityQueue是一个基于优先级堆的无界队列,其元素按自然顺序排序。 在创建时,我们可以为其提供一个负责对元素进行排序的比较器。 PriorityQueue 不允许空值,因为它们没有自然顺序,或者没有任何关联的比较器。 后,PriorityQueue不是线程安全的,进出队列的时间复杂度为O(log(n))。

30

你知道大O表示法(big-Onotation)吗? 你能举出不同数据结构的例子吗?

Big O 表示法描述了当数据结构中的元素数量增加时算法在坏情况下的扩展或执行情况。

Big O 表示法还可用于描述其他行为,例如内存消耗。 因为类实际上是数据结构,所以我们通常使用 big-oh 表示法来根据时间、内存和性能来选择佳实现。 Big O 表示法可以很好地说明大量数据上的性能。

31

使用无序数组与有序数组之间的权衡是什么?

有序数组的大优点是查找的时间复杂度为O(log n),而无序数组的查找时间复杂度为O(n)。 有序数组的缺点是插入操作的时间复杂度为O(n),因为值较大的元素需要向后移动,为新元素腾出空间。 相比之下,无序数组插入时间复杂度为常数 O(1)。

32

Java类框架的佳实践是什么?

根据应用程序的需要正确选择要使用的类型对于性能非常重要。 例如,如果元素的大小是固定的并且可以提前知道,我们应该使用Array而不是ArrayList。

一些类允许指定初始容量。 因此,如果我们能够估计出存储元素的数量,我们可以设置初始容量,以避免重新计算哈希值或扩大容量。

出于类型安全、可读性和稳健性的原因,始终使用泛型。 同时,使用泛型还可以避免运行时出现ClassCastException。

使用JDK提供的不可变类作为Map的key可以避免为我们自己的类实现hashCode()和equals()方法。

编程时接口优于实现。

当底层实际为空时,返回长度为0的或数组,不返回null。

33

Enumeration接口和Iterator接口有什么区别?

枚举的速度是迭代器的两倍,同时占用的内存更少。 然而,Iterator 比 Enumeration 安全得多,因为其他线程无法修改 iterator 正在遍历的中的对象。 同时,Iterator允许调用者删除底层中的元素,而这对于Enumeration来说是不可能的。

34

HashSet 和 TreeSet 有什么区别?

HashSet是通过哈希表实现的,因此它的元素是无序的。 add()、remove()、contains() 方法的时间复杂度为 O(1)。

另一方面,TreeSet是通过树结构实现的,其中的元素是有序的。 因此,add()、remove()、contains()方法的时间复杂度为O(logn)。

垃圾收集器¶

35

Java中垃圾回收的目的是什么? 垃圾收集何时发生?

垃圾收集的目的是识别并丢弃应用程序不再使用的对象,以释放和重用资源。

36

System.gc() 和 Runtime.gc() 会做什么?

这两个方法用于提示JVM进行垃圾回收。 但是,是否立即启动垃圾回收还是延迟启动取决于 JVM。

37

什么时候调用finalize()方法? 析构函数(终结)的目的是什么?

在释放对象占用的内存之前,垃圾收集器会调用对象的finalize()方法。 一般建议在该方法中释放对象所持有的资源。

38

如果对象的引用设置为null,垃圾收集器会立即释放该对象占用的内存吗?

不,该对象将在下一个垃圾收集周期中被回收。

39

Java堆的结构是什么样的? 堆中的代(PermGen 空间)是什么?

JVM的堆是运行时数据区,所有的类实例和数组都在堆上分配内存。 它是在 JVM 启动时创建的。 对象占用的堆内存由自动内存管理系统,即垃圾收集器回收。

堆内存由活对象和死对象组成。 幸存的对象可由应用程序访问,并且不会被垃圾收集。 死对象是应用程序无法访问且尚未被垃圾回收的对象。 在垃圾收集器回收这些对象之前,它们将始终占用堆内存空间。

40

串行收集器和吞吐量收集器有什么区别?

吞吐量收集器使用并行版本的年轻一代垃圾收集器,用于中型和大规模数据应用程序。 串行收集器对于大多数小型应用程序来说已经足够了(现代处理器上大约有 100M 内存)。

41

在Java中,什么时候对象可以被垃圾回收?

当当前使用该对象的应用程序无法访问该对象时,可以回收该对象。

42

垃圾回收是否发生在 JVM 的代中?

垃圾收集不会发生在代中。 如果代已满或超过阈值,则会触发完全垃圾收集(Full GC)。 如果你仔细观察垃圾收集器的输出,你会发现代也被收集了。 这是为什么正确的代大小对于避免 Full GC 非常重要。

© 版权声明
THE END
喜欢就亲吻一下吧
分享
评论 抢沙发
头像
评论一下幻城的文章吧
提交
头像

昵称

取消
昵称代码图片

    暂无评论内容