Java语言特点
来源:互联网 发布:linux怎样切换到root 编辑:程序博客网 时间:2024/06/18 10:00
* 平台无关性
java语言可以做到“一次编译、到处运行”。体现了其平台无关性的特点,那么这个是怎么做到的呢?
其实,java是一门解释性的语言,当编译java文件时,编译器会将文件编译成class字节码文件,只要响应环境中有JVM就能运行这个代码了(class字节码文件由JVM解释、执行)。
从中,我们也可以看到java 运行时的层次性,java源码 -> java class -> JVM -> 操作系统。
* 丰富的类库
java语言本身就内置许多类库,在开源社区还有诸多优秀的java类库。极大的缩减了Java开发人员的工作量,降低了工作复杂度,加快了项目进度。
并且,jar包形式的交付件保证了模块间的独立和解耦。
* Java程序初始化的顺序
Java程序的初始化一般遵循三个原则:
1、静态对象(变量)优先于非静态对象(变量)初始化
2、父类优先于之类进行初始化
3、按照成员变量的定义顺序进行初始化,即使变量散布于方法定义之中,它们依然在任何方法(包括构造函数)被调用之前先初始化。
实例化一个Java对象时,代码内部初始化顺序如下(优先级从高->低):
父类静态变量 -> 父类静态代码块 -> 之类静态变量 -> 之类静态代码块 -> 父类非静态变量 -> 父类非静态代码块 -> 父类构造函数 -> 之类非静态变量 -> 之类非静态代码块
-> 之类构造函数
* Java语言中为什么要保留基础数据类型
基本类型一直都是Java语言的一部分,主要是基于程序性能的考量,基本类型定义的变量是存放在栈中的,比如:int i = 5;而Integer j = newInteger(10);j只是一个
对象的应用,存放在栈中,而实际的数值10是存放在堆里的,堆的读写速度远不及栈。
再有就是基本类型定义的变量创建和销毁很快,而类定义的变量还要JVM去销毁。也是性能的考量。
一般建议使用包装类,虽然会牺牲一些转换效率,但可以避免持久化数据时产生的一些异常。
* Java 为什么不支持多继承
类定义属性和方法,用于描述某一类事物的抽象
而接口定义的是行为,并不限于任何具体的意向。
按照逻辑上来说,单继承更明确一个之类就应该是其父类代表的事物中的某个更具体、细分的类别,而不应该是既是这个东西又是那个东西。
而从实用角度来说单继承更易读、易维护、语义清晰、逻辑清楚。
而接口则不同,接口只定义一些公共行为。
类对接口的implements称作 实现 ,不叫继承
在Java中非要使用类似多继承的特性,在Java 8后可以使用“extends + implements(+ default 函数) + 组合” 来做。
* abstract class 和 interface 有什么不同
1、abstract class 里的抽象方法旨在设计的功能是跟当前类所代表的事物强相关的。
interface里的方法更抽象,更通用。
2、使用时,abstract class 的设计理念是 "is-a"的关系,而interface是“has-a”的关系。
3、abstract class里可以有功能性的函数体,interface没有(但java 8开始也有了)
4、abstract class里的成员变量跟普通class用法一致,而interface里的成员变量肯定是public static final的静态变量,而且必须是赋值了的。
不过,很多时候可以用interface替换abstract class。
* Object.hashCode
Object中的hashCode用于生成对象的哈希值。用于相关的数据结构和算法。
hashCode的常规协定:
1、在Java应用程序执行期间,在同一个对象上多次调用hashCode方法,必须一致的返回相同的整数,前提是equals比较中所用的信息没有被修改。
2、而一个应用程序重启后再运行,所返回的hashCode可以不一致。
3、如果equals方法返回的两个对象是相等的,那么hashCode值必须一致。
而如果equals方法返回的是不相等,这两对象的hashCode可能不一样,可能一样。
4、当equals被Override时,通常都需要连带Override hashCode方法。以保持hashCode方法的常规协定。
* Java 中String,StringBuffer,StringBuilder的区别
可变与不可变:
String 使用 private final char value[] 存储字符串的,即String存储的字符串是不可变的。
StringBuffer和StringBuilder存储的字符串是可变的。
是否多线程安全:
String 对象不可变,线程安全。
StringBuffer对方法加了同步锁,线程安全。
StringBuilder没有对方法加同步锁,线程不安全。
字符串拼接性能:
性能从高到低:StringBuilder -> StringBuffer -> String
* Java中有哪几种流
字节流和字符流
Java中所有的数据都是以流的形式保存的,流中保存的实际上全都是字节文件。即保存在文件里的都是字节信息。
Java中字节流输入\输出的抽象基类是:InputStream \ OutputStream。字符流的抽象基类:Reader \ Writer
字符流是由JVM在内存中将字节(字符集)转化为2个字节的Unicode字符为单位的字符而成的。
字符流(String)与字节流(byte[])互相转化时,涉及到对应的字符集,如果相互转化时未明确指定字符集类型,Java就会用操作系统的lang进行处理。
两者差异:
* 字节流在操作时候本身不会用到缓存区(内存),是与文件本身直接操作的。而字符流在操作的时候是使用到缓冲区的。
* 字节流在操作文件时,及时不关闭资源(close方法),文件也能输出。但字符流不使用close的话,不会输出任何内容(除非flush强制刷新)
* Java NIO
特点1:不阻塞。 阻塞IO在read,accept等方法时,当未满足条件时线程是阻塞的。
特点2:单线程多数据流。 阻塞IO在使用时,若有多个数据流,就需要创建多个线程。并频繁在线程间切换CPU,经常是无意义的CPU切换。
特点3:NIO是缓冲的。 标准java数据字节流,是不缓冲的。
* Java序列化
必须实现序列化的情况
1、需要通过网络发送对象,或对象的状态需要被持久化到数据库或文件中。
2、序列化能实现深复制,即可以复制引用的对象。
serialVersionUID
在序列化和反序列化过程中,serialVersionUID起着非常重要的作用。在反序列化过程中,通过serialVersionUID来判定类的兼容性,如果待序列化的对象与目标对象的serialVersionUID不一致,那么再反序列化时就会抛出InvalidClassException。
使用自定的serialVersionUID有3个优点:
1、提高程序的运行效率。如果在类中未显示的声明serialVersionUID,那么在序列化时会通过计算得到一个serialVersionUID值。通过显示声明serialVersionUID的方式省去了计算的过程。因此提高了运行效率。
2、提高程序不同平台上的兼容性。不显示声明serialVersionUID时,JVM会自动生成一个,这个值跟编译器有关。因为各个平台的编译器在计算serialVersionUID时可能会采用不同的计算方式。
3、增强程序各个版本的兼容性。通过显示声明的serialVersionUID在类发生变化时,由于serialVersionUID还是同一个,有机会做到兼容。而不显示声明serialVersionUID的类,由于编译器是根据类的内容计算serialVersionUID的,修改后的类的serialVersionUID完全有可能跟修改前的不一样,所以会不兼容。
序列化与外部序列化:
两者的主要区别是序列化时内置的API,只需要实现Serializable接口。而外部序列化时,Externalizable接口中的读写方法必须由开发人员自己实现。
Externalizable难度大,但因此把控制权交给了开发人员,开发人员可能根据场景实现更优的序列化读写方法。
* Java中堆和栈的区别
1、栈用于存放基础数据类型和对象的引用变量(局部变量)。堆主要用于存放new出来的对象。
* Lambda表达式中的Stream()和ParallelStream
Stream 表示集合处理任务串行执行
ParallelStream 表示集合处理任务并行执行(效率高很多)。
Stream和ParallelStream的选择:
1、是否需要并行?
2、任务之间是否是独立的?是否会引起任何竞态条件?
3、结果是否取决于任务的调用顺序?
* Java中的高阶函数
在Java 8以前,重用是建立在对象和类型系统之上。而Java 8中则将重用的概念更进一步,使用函数也能够实现代码的重用。所谓高阶函数,不要被其名字唬住了,实际上很简单:
* 将函数作为参数传入到另外一个函数中
* 函数的返回值可以是函数类型
* 在函数中创建另一个函数
如果一个方法接受一个函数式接口作为参数,那么我们可以传入以下类型作为参数:
* 匿名内部类(Anonymous Inner Class)
* Lambda表达式
* 方法或者构造器的引用(Method or Constructor Reference)
例:
interface
Function
{int execute(int x);}
实际使用中,会让map接收一个实现了Function的类的实例。private int[] array;public List(int[] array){ this.array = array;}public void map(
Function func
){for(int i = 0, len = this.array.length; i < len; i++){this.array[i] =
func
.execute
(this.array[i]); }}
public static void main(String[] args){List list = new List(new int[]{1, 2, 3, 4, 5}); list.print();list.map(new Function(){Public int execute(int x){return x * 2;}}),list.print();list.map(new Function(){ //匿名类方式Public int execute(int x){return x * 3;}}),list.print(); }
高阶函数代码重用性高
* java中的printf、print、println区别
printf 主要是继承了C语言的printf的一些特性,可以进行格式化输出
print 就是一般的标准输出,但是不换行
println和print基本没什么差别,就是最后会换行
* Java中内存泄露出现的场景
- Java语言特点
- Java语言的特点
- Java语言的特点
- JAVA语言的特点
- java语言的特点
- Java语言的特点
- java语言特点
- Java语言特点
- java语言特点
- Java语言的特点
- Java语言的特点
- Java语言特点
- JAVA语言的特点
- Java语言特点
- JAVA语言的特点
- Java语言的特点
- Java语言特点
- java语言的特点
- 原码, 反码, 补码补充
- C语言if判断语句中可以更改变量的值
- 事件驱动架构及应用
- 用Chrome开发工具调试并且同步文件
- jar 和 nohup 命令
- Java语言特点
- RecyclerView 下拉刷新和上拉加载
- 正确配置spring aop,在controller中使用AOP
- java实现简单的单点登录
- 半朴素贝叶斯分类器(周志华《机器学习》)
- [从头学声学] 第212节 辅音的数据
- 第 13 章 学习shell script
- 第三方支付平台:BeeCloud和Ping++对比
- 图像处理--linux opencv2多线程人脸识别