Java基础

一个Java文件中能否可以定义多个类



一个Java源文件里可以定义多个Java类,但最多只能有一个类public修饰。若源文件中包括了public类,源文件必须和该public类同名

构造器能否可被 重写重载



构造器 Constructor、重写 Override、重载 Overload
首先了解构造器

  • 构造器名称和类名相同,没有返回类型,不能使用return语句
  • 其作用是创建对象,初始化对象
  • 生成类的对象时自动执行,无需调用


    由此可得知构造器不能被重写,且没必要继承其构造器,因为当实例化子类时,底层会首先实例化父类


    构造器能够被重载

构造器有无参构造器有参构造器之分,而有参构造器的参数可以不同

重载和重写的区别



方法重载:

在同一个类中,方法名相同的,方法参数不同(参数类型、参数个数、参数顺序)

方法重载的作用:屏蔽了相同功能的方法由于参数不同所造成方法名称不同。

方法重载和方法的返回值类型无关,只是一般要求返回值类型相同。


方法重写:

重写是子类对从父类继承到的方法进一步扩展或者重新编写

  • 方法名,方法参数相同
  • 返回值范围小于等于父类方法的返回值类型
  • 访问修饰符范围大于等于父类
  • 抛出的异常类型小于等于父类

若父类方法被private访问修饰符修饰,则子类不能重写该方法

Java 面向对象编程三大特性

  • 封装
  • 继承
  • 多态


说说List,Set,Map三者的区别?

  • List:允许元素重复,允许纪录元素的添加顺序
  • Set: 不允许元素重复,不允许纪录元素的添加顺序
  • Map: 使用键值对存储。Key相当于Set集合,Value相当于List集合

String 为什么是不可变的



String 类中使用 final 关键字 修饰 字节数组 来保存字符串,所以 String 对象是不可变的

private final byte[] value;

java 8 之前使用字符数组保存,java 9 之后用字节数组保存,节省空间

String、StringBuffer 和 StringBuilder 的区别是什么


可变性

String 类中使用 final 关键字 修饰 字节数组 来保存字符串,所以 String 对象是不可变的

private final byte[] value;

而 StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder中也是使用字节数组 保存字符串 byte[] value 但是没有用 final关键字修饰,所以这两种对象都是可变的

byte[] value;


线程安全性

StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以可以保证线程安全。

而StringBuilder 并没有对方法加同步锁,所以不能保证线程安全。


性能

每次对String字符串类型进行修改的时候,都会生成一个新的String对象,然后将指针指向新的 String 对象。若进行大量的字符串修改操作时,会造成内存空间的浪费

StringBuffer ,StringBuffer 每次都会对对象本身进行操作,而不是生成新的对象并改变对象引用。

在执行操作数量不大的情况下(10W次拼接),两者性能差不多,当操作次数达到百万级别千万级别甚至更多时,使用 StringBuilder 相比使用 StringBuffer 能够获得 10% ~ 15% 左右的性能提升,但却要冒多线程不安全的风险。


使用场景

  • 操作少量的数据: 适用 String
  • 单线程中操作大量字符串数据修改时: 适用 StringBuilder
  • 多线程中操作大量字符串数据修改时: 适用 StringBuffer


    扩展

Java8 之前String底层存储字符串最小单位是一个char,用到两个byte,但是 Java8 是基于 latin1 (ISO-8859-1) 的,而这个latin1编码可以用一个byte标识。当你数据明明可以用到一个byte存储时,我们却用了一个最小单位char(两个byte),这时就多浪费了一个byte空间。

Java9 在这一方面进行了更新,现在的 Java9 是基于latin1/Utf-16 。

latin1 用 一个byte 标识,UTF-16 用 两个byte 标识

Java9 会自动识别用哪个编码,当数据只需用到1个byte时就会使用latin1 ,当数据需要用到2个byte时就会使用utf-16

这样便会节省了许多不必要的内存开销

自动装箱与拆箱

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

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

接口和抽象类的区别是什么

相同点

  • 都不能实例化

区别

  • 接口方法默认是public,abstract,且只能被这两个关键字修饰,方法不能被实现 (Java 8 开始接口方法可以有默认实现 default,静态实现 static
  • 抽象类可以同时定义抽象和非抽象方法,抽象方法可以有 public、protected 和 default 这些修饰符(抽象方法的存在就是为了被重写,所以不能使用 private 关键字修饰)
  • 接口中的成员变量,默认时是public static final,且只能够是静态不能被修改的,而且必须给其初始化赋值,而抽象类则不一定
  • 一个类可以实现多个接口,但只能继承一个抽象类。而且接口也可以继承多个接口类来扩展功能

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



帮助子类做初始化工作



== 与 equals区别

基本数据类型 " == " 是比较值

引用数据类型 " == " 和 equals() 两者都是 比较两个对象的引用地址

大多情况下我们关心的是数据而不是内存地址

所以我们一般重写 equals() 方法来比较对象的类型及内容

&和&&的区别

&和&&都可以用作逻辑与的运算符,表示逻辑与(and),当运算符两边的表达式的结果都为true时,返回true,若只要有一方为false,则结果为false。

&&还具有短路的功能,如果第一个表达式为false,则不再计算第二个表达式,减少一次判断次数

final 关键字修饰这三个地方:变量、方法、类,会有什么作用

  • final修饰的变量:表示常量,该变量一旦被初始化赋值之后便不能再次赋值

基本数据类型:表示的值不能改变

引用数据类型:所引用的地址值不能改变

  • final修饰方法时,如果父类拥有final修饰方法,子类继承后不能重写父类中被final修饰的方法
  • final修饰类时,表明这个类不能被继承。final 类中的所有成员方法都会被隐式地指定为 final 方法

final, finally, finalize的区别

  • final 用于声明变量,方法和类,分别表示变量不可变,方法不可覆盖,类不可被继承。
  • finally是异常处理语句结构的一部分,表示总是执行。
  • finalize()是Object类的一个方法,在GC垃圾回收器执行的时候会调用被回收对象的此方法,一般覆盖此方法用于释放非Java 资源,例如关闭文件等,但因为JVM不保证此方法总被调用,不推荐使用finalize来关闭资源,通常的做法是调用资源相关类提供显示的close()方法去释放资源

你重写过 hashcode 和 equals 么,为什么重写 equals 时必须重写 hashCode 方法?

是为了提高效率,采取重写hashcode方法,先进行hashcode比较,如果不同,那么就没必要在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大的效率提高是很明显的

描述深拷贝和浅拷贝

拷贝分 引用拷贝对象拷贝

引用拷贝 —— 即创建一个指向对象的引用变量的拷贝。相当于给一个新变量赋值引用地址操作。

对象拷贝 —— 克隆clone()方法

创建一个新的对象,把原来对象的信息拷贝到新对象, 它们的地址是不同的 。拷贝的对象信息分基本数据类型,引用类型。
对象拷贝分 浅拷贝深拷贝 ——克隆clone()方法

  • 浅拷贝

对于数据类型是基本数据类型的成员变量,直接进行值传递,修改不会有影响

对于数据类型是引用数据类型的成员变量,那么会进行引用传递,也就是将该成员变量的引用值(内存地址)复制一份给新的对象,修改会有连锁影响

  • 深拷贝

深拷贝是拷贝整个对象信息,除了基本类型的成员变量,还包括引用类型的成员变量。简单来说就是两个独立的个体互不相干。深拷贝相比于浅拷贝速度较慢并且花销较大。

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

当我们使用字节流去 读写 中文文本时,如果我们不知道编码类型就很容易出现乱码问题,所以 I/O流 就干脆提供了一个直接操作字符的字符流接口,方便我们平时对字符进行读写操作。

字符流底层还是通过字节流实现的,但是字符流自带缓冲区,当字符流执行读写操作时使用了缓冲区,再通过缓冲区操作文件,这样就减少了I/O流对磁盘的操作 ,从而优化性能

如果读写的是音频文件、图片等媒体文件还是要用回字节流比较好

Java 序列化中如果有些字段不想进行序列化,怎么办?

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

transient 关键字的作用是:阻止对象成员变量被序列化

当对象被反序列化时,被 transient 修饰的变量值不会恢复

transient 只能修饰变量,不能修饰类和方法

获取用键盘输入常用的两种方法

方法 1:通过 Scanner

Scanner input = new Scanner(System.in);
String s  = input.nextLine();
input.close();

方法 2:通过 BufferedReader

BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
input.close();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值