【Java基础】

基础概念

面向对象的三大特性

封装、继承、多肽。
封装是指类的内部信息进行隐藏、私有化,外部无法直接访问或影响内部的属性,只能通过特定的方法对封装的内容进行访问,提高了代码的安全性。
继承是指子类继承父类,子类可以获得父类的全部非private的属性和方法,且可以拥有一些父类所没有的方法和属性,提高了代码的复用性和逻辑性。
多肽是指不同类的对象在调用一个方法所呈现出的多种不同形态,提高了代码的可扩展性和可维护性。
在Java中有两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中同一方法)。

Java结构

接口和抽象类的区别

抽象类是对类的抽象,是用来捕捉子类通用特性的;接口是行为的抽象,是一种行为的规范。

参数抽象类接口
访问修饰符抽象方法可以是任意访问修饰符接口方法默认public,不能用其他修饰符
多继承一个类最多只能继承一个抽象类一个类可以实现多个接口
字段声明抽象类的字段声明可以是任意的接口的字段默认是 static 和 final的
添加新方法如果往抽象类中添加新的方法,可以提供默认的实现,因此不需要改变之前继承该类的代码。如果往接口总添加方法,需要改变实现该接口的类

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

普通类不能包含抽象方法,抽象类可以包含抽象方法。
抽象类不能直接实例化,普通类可以直接实例化。

在Java中定义一个不做事且没有参数的构造方法的作用

Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中没有参数的构造方法。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super() 来调用父类特定的构造方法,则编译时会发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法就是在父类里加一个不做事且没有参数的构造方法。

静态变量和普通变量的区别

静态变量是用static修饰的变量,静态变量被所有对象共享,属于类的,内存中只有一份,在类首次加载时会被初始化分配空间。非静态变量每次创建对象都会给成员变量分配内存空间,是属于对象的。

字符串

String是否可以被继承

不可以,因为String类似final类。

Java中的String a = "abc"和String a = new String(“abc”)的区别?

String a = “abc” 使用常量进行初始化,初始化后内存存储在String常量池中
String a = new String(“abc”) 创建字符串对象,JVM创建字符串对象但不存储于字符串池,会被分到堆内存中。

使用字符串初始化代码:String a = new String(“abc”);创建多少个对象?

上面一行代码将会创建1或2个字符串。如果在字符串常量池中已经有一个字符串“abc”,那么就只会创建一个“abc”字符串。如果字符串常量池中没有“abc”,那么首先会在字符串池中创建,然后才在堆内存中创建,这种情况就会创建2个对象了。

为什么字符串是不可变的?

因为String类是final类。

什么是String常量池?

字符串池是一个特殊的内存区域,用来存储字符串常量,可以提高内存的使用率,避免开辟多块空间存储相同的字符串,在创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中,并返回其引用。

使用equals和’=='进行字符串比较的差异?

字串中equals是重写的一个方法,比较字符串中value字符数组中字符是否一致,即比较的是字符串的值,==不仅比较字符串的值,而且还比较两个字符串所在内存地址是否相同。

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

可变性
String类中使用字符数组保存字符串,private final char value[],所以string对象是不可变的。StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,char[] value,这两种对象都是可变的。
线程安全性
String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
性能
每次对String 类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String 对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StirngBuilder 相比使用StringBuffer 仅能获得10%~15% 左右的性能提升,但却要冒多线程不安全的风险。

对于三者使用的总结

如果要操作少量的数据用 = String
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

Java String “+”连接符拼接字符串原理?

String字符串拼接通过StringBuilder走中间过程,通过append方法实现。
程序有大量字符串拼接时,建议直接StringBuilder实现,就不需要底层new很多临时String对象了。注意null参与拼接时会变成字符串"null"。

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

形式上: 字符常量是单引号引起的一个字符 字符串常量是双引号引起的若干个字符
含义上: 字符常量相当于一个整形值(ASCII值),可以参加表达式运算 字符串常量代表一个地址值(该字符串在内存中存放位置)
占内存大小 字符常量只占两个字节 字符串常量占若干个字节(至少一个字符结束标志)

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

indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。

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

HashMap 内部实现是通过 key 的 hashcode 来确定 value 的存储位置,因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快。

反射和代理

动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结
构上的变化。比如常见的 JavaScript 就是动态语言,除此之外 Ruby,Python 等也属于动态语言,
而 C、C++则不属于动态语言。从反射角度说 JAVA 属于半动态语言。

反射机制概念

在 Java 中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为 Java 语言的反射机制。

反射机制的应用场景

1、我们在使用JDBC连接数据库时使用Class.forName() 通过反射加载数据库的驱动程序
2、Spring 框架中通过XML配置模式装载Bean

  1. 将程序内所有 XML 或 Properties 配置文件加载入内存中;
    2)Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
    3)使用反射机制,根据这个字符串获得某个类的Class实例;
    4)动态配置实例的属性

Java获取反射的三种方法

1.通过new对象实现反射机制 2.通过路径实现反射机制 3.通过类名实现反射机制

public class Get {
    //获取反射机制三种方式
    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());
    }
}

异常

Error 和 Exception 区别是什么?

Error 类型的错误通常为虚拟机相关错误,如系统崩溃,内存不足,堆栈溢出等,编译器不会对这
类错误进行检测,JAVA 应用程序也不应对这类错误进行捕获,一旦这类错误发生,通常应用程序
会被终止,仅靠应用程序本身无法恢复;
Exception 类的错误是可以在应用程序中进行捕获并处理的,通常遇到这种错误,应对其进行处
理,使应用程序可以继续正常运行。

运行时异常和一般异常(受检异常)区别是什么?

运行时异常包括 RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常。 Java 编
译器不会检查运行时异常。
受检异常是Exception 中除 RuntimeException 及其子类之外的异常。 Java 编译器会检查受检异常。
RuntimeException异常和受检异常之间的区别:是否强制要求调用者必须处理此异常,如果强
制要求调用者必须进行处理,那么就使用受检异常,否则就选择非受检异常
(RuntimeException)。一般来讲,如果没有特殊的要求,我们建议使用RuntimeException异常。

Exception 又分为可检查(checked)异常和不检查(unchecked)异常,可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。
不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,具体根据需要来判断是否需要捕获,并不会在编译期强制要求。

JVM 是如何处理异常的?

在一个方法中如果发生异常,这个方法会创建一个异常对象,并转交给 JVM,该异常对象包含异
常名称,异常描述以及异常发生时应用程序的状态。创建异常对象并转交给 JVM 的过程称为抛出
异常。可能有一系列的方法调用,最终才进入抛出异常的方法,这一系列方法调用的有序列表叫做
调用栈。
JVM 会顺着调用栈去查找看是否有可以处理异常的代码,如果有,则调用异常处理代码。当 JVM
发现可以处理异常的代码时,会把发生的异常传递给它。如果 JVM 没有找到可以处理该异常的代
码块,JVM 就会将该异常转交给默认的异常处理器(默认处理器为 JVM 的一部分),默认异常处
理器打印出异常信息并终止应用程序。

throw 和 throws 的区别是什么?

Java 中的异常处理除了包括捕获异常和处理异常之外,还包括声明异常和拋出异常,可以通过
throws 关键字在方法上声明该方法要拋出的异常,或者在方法内部通过 throw 拋出异常对象。
throws 关键字和 throw 关键字在使用上的几点区别如下:

throw 关键字用在方法内部,只能用于抛出一种异常,用来抛出方法或代码块中的异常,受查异常
和非受查异常都可以被抛出。
throws 关键字用在方法声明上,可以抛出多个异常,用来标识该方法可能抛出的异常列表。一个
方法用 throws 标识了可能抛出的异常列表,调用该方法的方法中必须包含可处理异常的代码,否
则也要在方法签名中用 throws 关键字声明相应的异常

final、finally、finalize 有什么区别?

final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、
修饰变量表示该变量是一个常量不能被重新赋值。
finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法
finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码。
finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,Java 中允许使用
finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

Java常见异常有哪些

java.lang.IllegalAccessError:违法访问错误。当一个应用试图访问、修改某个类的域(Field)或
者调用其方法,但是又违反域或方法的可见性声明,则抛出该异常。
java.lang.InstantiationError:实例化错误。当一个应用试图通过Java的new操作符构造一个抽象
类或者接口时抛出该异常.
java.lang.OutOfMemoryError:内存不足错误。当可用内存不足以让Java虚拟机分配给一个对象
时抛出该错误。
java.lang.StackOverflowError:堆栈溢出错误。当一个应用递归调用的层次太深而导致堆栈溢出
或者陷入死循环时抛出该错误。
java.lang.ClassCastException:类造型异常。假设有类A和B(A不是B的父类或子类),O是A的
实例,那么当强制将O构造为类B的实例时抛出该异常。该异常经常被称为强制类型转换异常。
java.lang.ClassNotFoundException:找不到类异常。当应用试图根据字符串形式的类名构造类,
而在遍历CLASSPAH之后找不到对应名称的class文件时,抛出该异常。
java.lang.ArithmeticException:算术条件异常。譬如:整数除零等。
java.lang.ArrayIndexOutOfBoundsException:数组索引越界异常。当对数组的索引值为负数或
大于等于数组大小时抛出。
java.lang.IndexOutOfBoundsException:索引越界异常。当访问某个序列的索引值小于0或大于
等于序列大小时,抛出该异常。
java.lang.InstantiationException:实例化异常。当试图通过newInstance()方法创建某个类的实
例,而该类是一个抽象类或接口时,抛出该异常。
java.lang.NoSuchFieldException:属性不存在异常。当访问某个类的不存在的属性时抛出该异
常。
java.lang.NoSuchMethodException:方法不存在异常。当访问某个类的不存在的方法时抛出该
异常。-
java.lang.NullPointerException:空指针异常。当应用试图在要求使用对象的地方使用了null时,
抛出该异常。譬如:调用null对象的实例方法、访问null对象的属性、计算null对象的长度、使用
throw语句抛出null等等。
java.lang.NumberFormatException:数字格式异常。当试图将一个String转换为指定的数字类
型,而该字符串确不满足数字类型要求的格式时,抛出该异常。
java.lang.StringIndexOutOfBoundsException:字符串索引越界异常。当使用索引值访问某个字
符串中的字符,而该索引值小于0或大于等于序列大小时,抛出该异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值