Java基础

2.1.1.面向对象和面向过程的区别

面向过程:面向过程性能比面向对象高。因为调用类时需要实例化,开销比较大,比较消耗资源,当性能是重要考量因素的时候,一般是面向过程开发。但是,面向过程没有面向对象易维护,易复用,易拓展。

面向对象:面向对象易维护,易拓展,易复用。因为面向对象有封装,继承,多态的特点,可以设计出低耦合的系统,使系统更加灵活,更加容易维护。但是面向对象性能比面向过程低。

Java性能低的根本原因是:Java是半编译语言,最终执行的代码并不是可以直接被CPU执行的二进制机械码。面向过程的语言大多数是直接编译成机械码在电脑上执行。

2.1.2Java语言有哪些特点?

1.简单易学

2.面向对象(封装,继承,多态)

3.平台无关性(Java虚拟机实现平台无关性)

4.可靠性

5.安全性

6.支持多线程

7.支持网络编程并且很方便

8.编译与解释共存 

 2.1.3JVM JDK JRE

2.1.3.1JVM

Java虚拟机(JVM)是运行Java字节码的虚拟机。JVM有针对不同系统的特定实现,目的是使用相同的字节码,它们都会给出相同的操作。“一次编译,随处可运行”


什么是字节码?字节码的好处是什么?

在Java中,JVM可以理解的代码叫做字节码(.class文件),它不面向任何特定的处理器,只面向虚拟机。Java通过字节码的方式,在一定程度上解决了传统解释型语言效率低的问题,同时又保留了解释型语言可移植的特点。所以Java程序运行时比较高效,而且字节码不针对一种特定的机器,因此,Java程序无需重新编译就可在不同操作系统的电脑上运行。


Java程序从源代码到运行一般3步:


JDK和JRE

JDK包括JRE,还有编译器和工具。能够创建和编译程序。

JRE是Java运行时的环境。它是运行已编译Java程序所需所有内容的集合,包括JVM,Java类库,Java命令和其他的一些基础构建。但是它不能创建新程序。

一般来说运行Java程序只需要JRE,进行Java编程才需要安装JDK。但用JSP部署Web应用程序的时候,应用程序会将JSP转换成Java servlet,并且需要JDK来编译servlet。


Oracle JDK和OpenJDK的对比

Oracle JDK基于OpenJDK 7构建,添加了部署代码,封闭的源代码排队组件,一些开源的第三方组件以及一些零碎的东西。

1.OpenJDK完全开源,Oracle JDK是OpenJDK的一个实现,不是完全开源

2.Oracle JDK更稳定,有更多的类和一些错误的修复

3.在响应性和JVM性能方面,Oracle JDK更好性能

4.Oracle JDK不会为即将发布的版本提供长期支持,必须更新到最新版本获取

5.Oracle JDK根据二进制代码许可协议获得许可,而OpenJDK根据GPL v2许可获得许可

2.1.5Java和C++的区别?

1. 都是面向对象的语言,都支持封装,继承,多态

2.Java不提供指针来直接访问内存,程序内存更安全

3.Java的类是单继承的,C++支持多继承,但Java的接口支持多继承

4.Java有自动内存管理机制,不需要程序员手动释放内存

5.C语言中,字符串或字符数组最后都会有一个'\0'表示结束。Java没有结束符这一概念

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

1.形式上:字符常量是单引号引起的一个字符;字符串常量是双引号引起的若干个字符

2.含义上:字符常量相当于一个整形值(ASCII值),可以参加表达式的运算;字符串常量代表一个地址值(该字符串常量在内存中的存放位置) 

3.占内存大学:字符常量只占2字节,字符串常量占若干个字节(char在Java中占两个字节)


题外话:

float占4字节,double占8字节,int占4字节,long占8字节,short占2字节,char占2字节,byte占1字节

2.1.7构造器Constructor是否可被override?

Constructor不能被override(重写),但是可以被overload(重载),你可以看到一个类中有多个构造函数的情况。 

2.1.8重载和重写的区别

重载就是同样的一个函数,根据输入数据的不同,做出不同的处理
重写就是当子类继承父类的相同方法,输入数据一样,但要做出有别于父类的响应时,就要覆盖父类方法


重载:发生在同一个类中,方法名必须相同,参数类型不同,个数不同,顺序不同,方法返回值和访问修饰符可以不同。

综上:同一个类中,多个同名方法根据传参的不同执行不同的逻辑


重写:重写发在运行期,子类对父类的允许访问的方法的实现过程进行重新编写

1.方法名,参数列表必须相同,抛出的异常类型范围小于等于父类,访问修饰符范围大于等于父类。

2.如果父类的方法访问修饰符为private/final/static则子类就不能重写该方法,但是被static修饰的方法能够被再次声明

3.构造方法无法被重写

综上:重写就是对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变

两同两小一大:方法名相同,形参列表相同

两小:子类方法返回值类型比父类方法返回值类型相等或更小,异常类也是

(如果返回值类型是基本类型,则不能变,如果返回值是引用类型,可以返回引用类型的子类)

一大:子类方法的访问权限比父类方法的访问权限更大或相等

2.1.9Java面向对象编程三大特征:封装zilei,继承,多态

封装:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法

继承:继承是使用已存在的类的定义作为基础建立新的类的技术,新类的定义可以增加新的数据或新的功能,也可以使用父类的功能,但不能选择性地继承父类。通过继承我们可以很方便的复用以前的代码。

1.子类可以拥有父类的所有属性和方法(包括私有属性和方法),但是父类中的私有属性和方法子类无法访问只是拥有

2.子类可以拥有自己的方法,即子类可以对父类进行拓展

3.子类可以用自己的方式实现父类的方法

多态:所谓多态就是指程序中定义的引用变量所执行的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在运行期间才确定,即一个用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底时那个类中实现的方法,必须由程序运行期间才能决定

在Java中由两种形式可以实现多态:继承(多个子类对同一方法的重写)和接口(实现接口并覆盖接口中的同一方法)

 2.1.10String StringBuffer StringBuilder的区别是什么?String为什么是不可变的?


可变性:

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

而StringBuilder与StringBuffer,没有使用final保存关键字,可变


线程安全性:

String中的对象是不可变的,也就可以理解成常量,线程安全

StringBuilder和StringBuffer的父类定义了一些字符串的操作,

StringBuffer对方法加了同步锁,是安全的。而StringBuilder没有对方法加同步锁,所以是不安全


性能:

String 每次对String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。

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

相同情况下StringBuilder相比使用StringBuffer仅能获取10%-15%的性能提升,却要冒多线程不安全的风险。


总结:

1.操作少量的数据:使用String

2.单线程操作字符串缓冲区下操作大量数据:适用StringBuilder

3.多线程操作字符串缓冲区下操作大量数据:使用StringBuffer

2.1.11 自动装箱与拆箱

装箱:将基本类型用它们对应的引用类型包装起来

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

2.1.12 在一个静态方法内调用一个非静态成员为什么是非法的?

由于静态方法可以不通过对象调用,在静态方法内,不能调用其他非静态变量,也不可以访问非静态变量成员 

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

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

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

1.接口的方法默认是public,所有方法在接口中不能有实现 (Java8开始接口方法可以有默认实现),而抽象类可以有非抽象的方法。

2.接口中除了static,final变量,不能有其他变量,而抽象类不一定

3.一个类可以实现多个接口,但只能实现一个抽象类。接口本身可以通过extends关键字拓展多个接口

4.接口方法默认修饰符是public,抽象方法可以有public,protect和default这些修饰符(抽象方法就是为了被重写所以不能被private修饰)

5.从设计层面讲,抽象是对类的抽象,是一种设计模板,而接口是对行为的抽象,是一种行为规范


在JDK7或更早的版本中,接口里面只能由常量变量和抽象方法。这些接口方法必须由选择实现接口的类实现。

JDK8的时候接口可以有默认方法和静态方法功能

JDK9在接口中引入了私有方法和私有静态方法

 2.1.15成员变量与局部变量的区别有哪些

1.从语法形式上看:成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数,成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问修饰符及static所修饰;成员变量和局部变量都能被final修饰

2.从变量在内存中的存储方式来看:如果成员变量是使用static修饰的,那么这个成员变量是属于类的,如果没使用static,这个成员变量是属于实例的。对象存于堆内存中,如果局部变量类型为基本数据类型,那么存储在栈内存,如果为引用数据类型,那么存放的是指向堆内存对象的引用或是指向常量池中的地址。

3.从变量在内存中的生存时间:成员变量是对象的一部分,它随着对象的创建而存在,而局部变量随着方法的调用而自动消失。

4.成员变量如果没有被赋初值,成员变量会自动以类型的默认值而赋值(一种情况例外:被final修饰的成员变量,也必须显式地赋值),而局部变量则不会自动赋值

2.1.16 创建一个对象用什么运算符?对象实体与对象引用有什么不同?

new运算符,new创建对象实例(对象实例在堆内存中),对象引用指向对象实例(对象引用存放栈中)。一个对象引用可以指向一个对象或不指向对象(一根绳子可以不系气球,也可以系一个气球);一个对象可以有n个引用指向它(可以用n条绳子系住一个气球)。

2.1.17 什么是方法的返回值?返回值在类的方法的作用什么?

方法的返回值是我们获取到的某个方法体中代码执行后产生的结果(前提是能产生)。

返回值在类中作用,接收出结果,使它可以用于其他的操作。

 2.1.18一个类的构造方法的作用是什么?若一个类没有声明构造方法,该程序能正确执行吗?

完成对类对象实例化的工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。

2.1.19构造方法有哪些特征?

1.名字与类名相同

2.没有返回值,但不能用void声明构造函数

3.生成类的对象时自动执行,无需调用

2.1.20 静态方法和实例方法有哪些不同?
1.在外部调用静态方法时,可以使用“类名.方法名”的方式,也可以使用“对象名.方法名”。而实例方法只有后面这种方式,调用静态对象可以无需创建对象。

2.静态方法在访问本类的成员时,只允许访问静态成员 ,不允许方法实例成员变量和实例方法;实例方法则无此限制。

2.1.21对象的相等与指向他们的引用相等,两者有什么不同?

对象的相等,比的是内存中存放的内容是否相等。而引用相等,比较的是他们指向的内存地址是否相等 

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

帮助子类做初始化工作 

2.1.23==与equals

==:它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象 (基本数据类型==判断的是值,引用数据类型==比较的是内存地址)。

equals():它的作用也是判断两个对象是否相等,但它一般有两种使用情况:

1.类没有覆盖equals()方法。则通过equals()方法比较两个对象是,等价与==

2.类覆盖率equals()方法,一般覆盖equals()方法来比较两个对象的内容是否相等;若它们内容相等,则返回true(即,认为这两个对象相等)

说明:

String中的equals方法是被重写过的,因为object的equals方法是比较的对象内存地址,而String的equals方法比较多是对象的值。

当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有酒吧它赋值给当前引用。如果没有就在常量池中创建一个String对象

2.1.24hashCode与equals(重要)

1)hashCode()介绍

hashCode()的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置hashCode。hashCode()定义在JDK的Object类中,就意味着Java中的任何类都包含有hashCode()函数。另外需要注意的是:Object的hashCode方法是本地方法,也就是c语言或c++语言实现,该方法通常用来将对象的内存地址转换成整数之后返回。

散列表存储的是键值对(key-value),它的特点是:能根据“键”快速检索出“值”。这其中就利用到了散列码

2)为什么要有hashCode?

我们以“HashSet"如何检查重复为例子来说明为什么要有hashCode?

当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他已经加入的对象的hashcode值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相等。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就重新散列到其他位置。这样就大大减少了equals的次数,提高了执行速度。

3.为什么重写equals一定要重写hashcode方法?************晕了************

如果两个对象相等,则hashcode一定相同。两个对象相等,对两个对象分别调用equals方法都返回true。
对象的hashCode  如果相等,对象不一定相等。hashCode不相等则两个对象一定不相等。哈希表,在插入元素时,都会先判断hashCode是否已经在哈希表种,如果没有,则直接插入。如果哈希表种已经有相同hashCode的key,则需要再调用equals方法判断 key对应的value是否与插入元素相等。
所以,重写equals()必须重写hashCode() 是因为需要避免这种情况的出现:equas()判断相等,但是两个对象hashCode()却不相等。否则,结合哈希表插入元素的步骤,会发现可能会插入相同key值的元素。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值