java面试题——java基础

  1. 面向对象和面向过程的区别
    面向过程:面向过程性能比面向对象高。因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix 等一般采用面向过程开发。 但是,面向过程没有面向对象易维护、易复用、易扩展。
    面向对象: 面向对象易维护、易复用、易扩展。因为面向对象有封装、继承、多态性的特性,所以可以设计出低耦合的系统,使系统更加灵活、更加易于维护。但是,面向对象性能比面向过程低。
  2. JDK和JRE
    JDK是Java Development Kit(java开发工具),它是功能齐全的Java SDK。它拥有JRE所拥有的一切,还有编译器(javac) 和工具(如javadoc和jdb)。它能够创建和编译程序。
    JRE是Java运行时环境。它是运行已编译Java程序所需的所有内容的集合,包括Java虚拟机(JVM),Java 类库,java 命令和其他的一些基础构件。但是,它不能用于创建新程序。如果你只是为了运行一下Java程序的话,那么你只需要安装JRE就可以了。如果你需要进行一些Java编程方面的工作,那么你就需要安装JDK了。但是,这不是绝对的。有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使
    用JSP部署Web应用程序,那么从技术上讲,您只是在应用程序服务器中运行Java程序。那你为什么需要JDK呢?因为应用程序服务器会将JSP转换为Java servlet,并且需要使用JDK来编译servlet。
  3. Java和C++的区别?
    都是面向对象的语言,都支持封装、继承和多态
    Java不提供指针来直接访问内存,程序内存更加安全
    Java的类是单继承的,C++支持多重继承;虽然Java的类不可以多继承,但是接口可以多继承。
    Java 有自动内存管理机制,不需要程序员手动释放无用内存
    ●在C语言中,字符串或字符数组最后都会有一个额外的字符‘\0’来表示结束。但是,Java语言中没有结束符这一概念。
  4. 字符型常量和字符串常量的区别?
    形式上:字符常量是单引号引起的一个字符;字符串常量是双引号引起的若干个字符
    含义上:字符常量相当于一个整型值( ASCII值),可以参加表达式运算;字符串常量代表一个地址值(该字符串在内存中存放位置)
    占内存大小字符常量只占2个字节;字符串常量占若干个字节(注意: char在Java中占两个字节)
    在这里插入图片描述5. 构造器Constructor是否可被override?
    构造器不能被override (重写) ,但是可以overload (重载) ,所以你可以看到一个类中有多个构造函数的情况。
    Java的构造器并不是函数,所以他并不能被继承
     构造器的修饰符比较的有限,仅仅只有public private protected这三个,其他的例如任何修饰符都不能对其使用,也就是说构造器不允许被成名成抽象、同步、静态等等访问限制以外的形式
     因为构造器不是函数,所以它是没有返回值的,也不允许有返回值。但是这里要说明一下,构造器中允许存在return语句,但是return什么都不返回,如果你指定了返回值,虽然编译器不会报出任何错误,但是JVM会认为他是一个与构造器同名的函数罢了,这样就会出现一些莫名其妙的无法找到构造器的错误,这里是要加倍注意的。
  5. 重载和重写的区别
    重载
    发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。但是不能只有返回值不同
    在这里插入图片描述重写
    重写是子类对父类的允许访问的方法的实现过程进行重新编写,发生在子类中,方法名参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。另外,如果父类方法访问修饰符为private则子类就不能重写该方法。也就是说方法提供的行为改变,而方法的外貌并没有改变。
  6. Java面向对象三大特性:封装继承多态
    封装
    封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。
    继承
    继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码。
    关于继承如下3点请记住:
    1. 子类拥有父类对象所有的属性和方法(包括私有属性和私有方法),但是父类中的私有属性和方法子类是无法访问,只是拥有。
    2. 子类可以拥有自己属性和方法,即子类可以对父类进行扩展。.
    3. 子类可以用自己的方式实现父类的方法。
      多态
      所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
      概述
      在设计一个方法时,通常希望该方法具备定的通用性。 例如要实现一个动物叫的方法,由于每种动物的叫声是不同的,因此可以在方法中接收一个动物类型的参数,当传入猫类对象时就发出猫类的叫声,传人犬类对象时就发出犬类的叫声。在同一个方法中,这种由于参数类型不同而导致执行效果各异的现象就是多态
  7. String StringBuffer和StringBuilder的区别是什么? String为什么是不
    可变的
    ?
    1. 可变性
      简单的来说: String 类中使用final关键字修饰字符数组来保存字符串,privatefinal char value[],所以String对象是不可变的。 Java 9 之后String类得我实现改用byte[] 数组存储字符串 private final byte[] value
      StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串char []value但是没有用final关键字修饰,所以这两种对象都是可变的。
      StringBuilder与StringBuffer的构造方法都是调用父类构造方法也就是
      AbstractStringBuilder实现的,大家可以自行查阅源码。
    2. 线程安全性
      String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、 insert、 indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
    3. 性能
      每次对String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StringBuilder相比使用StringBuffer仅能获得10%~15%左右的性能提升,但却要冒多线程不安全的风险。
    4. 对于三者使用的总结:
      1.操作少量的数据:适用String
      2.单线程操作字符串缓冲区下操作大量数据:适用StringBuilder
      3.多线程操作字符串缓冲区下操作大量数据:适用StringBuffer
  8. 自动装箱与拆箱
    ●装箱:将基本类型用它们对应的引用类型包装起来;
    ●拆箱:将包装类型转换为基本数据类型;
  9. 在一个静态方法内调用一个非静态成员为什么是非法的?
    由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。
  10. 在Java中定义一个不做事且没有参数的构造方法的作用
    Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super( )来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
  11. 接口和抽象类的区别是什么?
    1. 接口的方法默认是public,所有方法在接口中不能有实现(Java 8开始接口方法可以有默认实现),而抽象类可以有非抽象的方法。
    2. 接口中除了static、final 变量,不能有其他变量,而抽象类中则不一定。
    3. 一个类可以实现多个接口,但只能实现一个抽象类。接口自己本身可以通过extends关键字扩展多个接口。
    4. 接口方法默认修饰符是public,抽象方法可以有public、protected 和default这些修饰符(抽象方法就是为了被重写所以不能使用private关键字修饰! )。
    5. 从设计层面来说,抽象是对类的抽象,是一种模板设计,而接口是对行为的抽象,是一种行为的规范。
      备注:
      1.在JDK8中,接口也可以定义静态方法,可以直接用接口名调用。实现类和实现是不可以调用的。如果同时实现两个接口,接口中定义了一样的默认方法,则必须重写,不然会报错。
      2.jdk9 的接口被允许定义私有方法。
  12. 成员变量与局部变量的区别有哪些?
    1. 从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数;成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所修饰;但是,成员变量和局部变量都能被final所修饰。
    2. 从变量在内存中的存储方式来看:如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没有使用static修饰,这个成员变量是属于实例的。而对象存在于堆内存,局部变量则存在于栈内存
    3. 从变量在内存中的生存时间上看:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。
    4. 成员变量如果没有被赋初值:则会自动以类型的默认值而赋值(一种情况例外:被final修饰的成员变量也必须显式地赋值),而局部变量则不会自动赋值。
  13. 静态方法和实例方法有何不同
    static详解
    1. 在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象
    2. 静态方法在访问本类的成员时,只允许访问静态成员(即静态成员变量和静态方法 不需要使用this),而不允许访问实例成员变量和实例方法;实例方法则无此限制。
    3. 静态内部类可以声明普通成员变量和方法,而普通内部类不能声明static成员变量和方法。
    4. 静态内部类可以单独初始化:
      Inner i = new Outer.Inner();
      普通内部类初始化:
      Outer o = new Outer();
  14. 静态代码块
    1. 内部只能调用静态方法与静态变量 已经静态内部类的静态方法与静态变量
    2. 静态代码块只能写在类中方法外,不能写在方法中,它会随着类的加载而优先于各种代码块和构造方法的加载,并且只会加载一次,如果出现多个静态代码块,会按照书写顺序加载
    3. 静态代码块不能出现在任何方法体内
  15. == 与equals(重要)
    == :它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)。
    equals() :它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
    ●情况1:类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。
    ●情况2:类覆盖了equals()方法。一般,我们都覆盖equals()方法来比较两个对象的内容是否相等;若它们的内容相等,则返回true (即,认为这两个对象相等)。
  16. 访问权限修饰符public. private. protected,以及不写(默认)时的区别
    在这里插入图片描述19. 如何理解 clone对象
    17.1 为什么要用clone?
    在实际编程过程中,我们常常要遇到这种情况:有一个对象A,在某一时刻A中已经包含了一些有效值,此时可能会需要一个和A完全相同新对象B,并且此后对B任何改动都不会影响到A中的值,也就是说,A与B是两个独立的对象,但B的初始值是由A对象确定的。在Java语言中,用简单的赋值语句是不能满足这种需求的。要满足这种需求虽然有很多途径,但实现clone ()方法是其中最简单,也是最高效的手段。
    17.2 new 一个对象的过程和clone 一个对象的过程区别
    new操作符的本意是分配内存。程序执行到new操作符时,首先去看new操作符后面的类型,因为知道了类型,才能知道要分配多大的内存空间。**分配完内存之后,再调用构造函数,填充对象的各个域,这一步叫做对象的初始化,**构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。
    clone在第一步是和new相似的,都是分配内存,调用clone方法时,分配的内存和原对象(即调用clone方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域,填充完成之后, clone 方法返回, -一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。
    17.3 clone对象的使用
    复制对象和复制引用的区别
    在这里插入图片描述可以看出,打印的地址值是相同的,既然地址都是相同的,那么肯定是同一个对象。p和p1只是引用而已,他们都指向了一个相同的对象Person(23,“zhang” )。可以把这种现象叫做引用的复制。 上面代码执行完成之后, 内存中的情景如下图所示:
    在这里插入图片描述在这里插入图片描述
    从打印结果可以看出,两个对象的地址是不同的,也就是说创建了新的对象,而不是把原对象的地址赋给了一 个新的引用变量:
    在这里插入图片描述17.3 深拷贝和浅拷贝
    上面的示例代码中,Person 中有两个成员变量,分别是name和age,name 是String类型,age 是int类型。
    由于age是基本数据类型,那么对它的拷贝没有什么疑议,直接将一个4字节的整数值拷贝过来就行。但是name是String类型的,它只是一个引用,指向一个真正的String对象,那么对它的拷贝有两种方式 直接将原对象中的name的引用值拷贝给新对象的name字段,或者是根据原 Person对象中的name指向的字符串对象创建一个新的相同的字符串对象,将这个新字符串对象的引用赋给新拷贝的Person对象的name字段 这两种拷贝方式分别叫做浅拷贝和深拷贝。深拷贝和浅拷贝的原理如下图所示:
    在这里插入图片描述在这里插入图片描述如何进行深拷贝:
    想要深拷贝一个对象,这个对象必须要实现Cloneable接口,实现clone
    方法,并且在clone方法内部,把该对象引用的其他对象也要clone一份, 这就要求这个被引用的对象必须也要实现Cloneable接口并且实现clone方法
    。那么,按照上面的结论,实现以下代码Body 类组合了Head类,要想深拷贝Body类,必须在Body类的clone方法中将Head类也要拷贝一份。代码如下:
    在这里插入图片描述
  17. 一个类的构造函数如果被设置成私有 那么该类不能被继承
    如果该类的有多个构造函数 无参空构造被设置成私有 子类需要有同参数的构造方法在这里插入图片描述
    在这里插入图片描述
  18. java回调
    回调的核心就是 回调方将本身即this传递给调用方.这样调用方就可以在调用完毕之后告诉回调方它想要
    知道的信息。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值