首页 > 编程 > Java > 正文

Java中的各种区别

2019-11-08 19:25:34
字体:
来源:转载
供稿:网友

一 i 和 I的区别二 和区别短路位运算三 方法重写和方法重载的区别概念override重写覆盖overload重载过载多态性语法特点Override 特点Overload 特点总结override重写覆盖overload重载过载四 抽象类和接口的区别概念抽象类接口语法方面在应用上五 arraylist和linkedlist区别 接口实现形式性能六 arraylist和vector区别线程安全容量增加七 hashmap和hashtable线程安全null八 转发和重定向的区别九 session和cookie的区别十 heap和stack有什么区别十一 sleep和 wait有什么区别简述详述面试提示十二 StringStringBuffer和StringBuilder的区别概念StringStringBufferStringBuilder三者区别String类型和StringBuffer的主要性能区别使用策略十三Iterator和ListIterator的区别

一 i++ 和 ++I的区别

它们都等价于i=i+1,区别在于i++是先给表达式赋值,再给i自加;++i先自加,再赋值

二 &&和&区别:

1 短路

&&具有短路的功能,如果第一个表达式为false,则不再计算第二个表达式

2 位运算

&可以用作位运算符,当&操作符两边的表达式不是布尔类型时,&表示按位与操作

三 方法重写和方法重载的区别

1 概念

override(重写,覆盖)

如果在子类中定义某方法与其父类某方法有相同的名称和参数,我们说父类中该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了.

overload(重载,过载)

如果在一个类中定义了多个同名的方法,它们或有不同的参数个数或有不同的参数类型或有不同的参数次序,则称为方法的重载(Overloading)。不能通过访问权限、返回类型、抛出的异常进行重载.

2 多态性

方法的重写(Overriding)和重载(Overloading)是java方法多态性的不同表现。重写(Overriding)是父类与子类之间多态性的一种表现,而重载(Overloading)是一个类中多态性的一种表现。

3 语法特点:

Override 特点

1、覆盖的方法的标志必须要和被覆盖的方法的标志完全匹配,才能达到覆盖的效果; 2、覆盖的方法的返回值必须和被覆盖的方法的返回一致; 3、覆盖的方法所抛出的异常必须和被覆盖方法的所抛出的异常一致,或者是其子类; 4、被覆盖的方法不能为PRivate,否则在其子类中只是新定义了一个方法,并没有对其进行覆盖。

Overload 特点

1、在使用重载时只能通过不同的参数样式。例如,不同的参数类型,不同的参数个数,不同的参数顺序(当然,同一方法内的几个参数类型必须不一样,例如可以是fun(int, float), 但是不能为fun(int, int)); 2、不能通过访问权限、返回类型、抛出的异常进行重载; 3、方法的异常类型和数目不会对重载造成影响; 4、对于继承来说,如果某一方法在父类中是访问权限是priavte,那么就不能在子类对其进行重载,不会达到重载的效果。

4 总结

override(重写,覆盖)

1、方法名、参数、返回值相同。 2、子类方法不能缩小父类方法的访问权限。 3、子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。 4、存在于父类和子类之间。 5、方法被定义为final不能被重写。

overload(重载,过载)

1、参数类型、个数、顺序至少有一个不相同。 2、不能重载只有返回值不同的方法名。 3、存在于父类和子类、同类中。

四 抽象类和接口的区别

1 概念

抽象类

含有abstract修饰符的类即为抽象类,抽象类不能实例化。含有抽象方法的类必须定义为抽象类,抽象类中的方法不必是抽象的。抽象类中定义的抽象方法必须在具体子类中实现,所以,不能有抽象构造方法或抽象静态方法。

接口

接口可以说成是抽象类中的一种特例,接口中的所有方法都必须是抽象的。接口中的方法默认为public abstract类型,接口中的成员变量默认为public static final类型。

2 语法方面:

1.抽象类可以有构造方法、普通成员变量、非抽象的普通方法、静态方法,接口中不能有构造方法。2 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。3 抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。一个类可以实现多个接口,但只能继承一个抽象类。

3 在应用上:

接口是在系统架构设计方面发挥作用,用于定义模块之间的通信契约。而抽象类是在代码实现方面发挥作用,可以实现代码的重用,例如,模板方法设计模式

五 arraylist和linkedlist区别 (接口,实现形式,性能)

ArrayList实现了List接口,基于线性数组实现,随机访问性能出色,由于长度改变是需要需要反复调整数组空间大小做增删操作时的时间消耗较大; LinkedList实现了List和Deque接口,内部以链表的形式保存,随机访问性能较差,插入、删除性能出色

六 arraylist和vector区别(线程安全,容量增加)

Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。 当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍,而ArrayList只增加50%的大小,这样,ArrayList就有利于节约内存空间。

七 hashmap和hashtable(线程安全,null)

HashTable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比HashTable的性能高一点;但如果多个线程访问同一个Map对象时,使用HashTable实现类会更好 HashTable不允许使用null作为key和value,如果试图把null值放进Hashtable中,将会引发NullPointerException异常,但HashMap可以使用null作为key或value

八 转发和重定向的区别

1.重定向时浏览器上的网址改变,转发是浏览器上的网址不变2.重定向实际上产生了两次请求,转发只有一次请求 重定向:发送请求 ->服务器运行->响应请求,返回给浏览器一个新的地址与响应码–>浏览器根据响应码,判定该响应为重定向,自动发送一个新的请求给服务器,请求地址为之前返回的地址–>服务器运行–>响应请求给浏览器 转发:发送请求->服务器运行->进行请求的重新设置,例如通过request.setAttribute(name,value)–>根据转发的地址,获取该地址的网页–>响应请求给浏览器3.重定向时的网址可以是任何网址,转发的网址必须是本站点的网址4 携带的数据 重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。 转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。

九 session和cookie的区别

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE。4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

十 heap和stack有什么区别

java的内存分为两类,一类是栈内存,一类是堆内存。 栈内存是指程序进入一个方法时,会为这个方法单独分配一块私属存储空间,用于存储这个方法内部的局部变量,当这个方法结束时,分配给这个方法的栈会释放,这个栈中的变量也将随之释放。 堆是与栈作用不同的内存,一般用于存放不放在当前方法栈中的那些数据,例如,使用new创建的对象都放在堆里,所以,它不会随方法的结束而消失。方法中的局部变量使用final修饰后,放在堆中,而不是栈中。

十一 sleep()和 wait()有什么区别?

1 简述

sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。 wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

2 详述

sleep就是正在执行的线程主动让出cpu,cpu去执行其他线程,在sleep指定的时间过后,cpu才会回到这个线程上继续往下执行,如果当前线程进入了同步锁,sleep方法并不会释放锁,即使当前线程使用sleep方法让出了cpu,但其他被同步锁挡住了的线程也无法得到执行。wait是指在一个已经进入了同步锁的线程内,让自己暂时让出同步锁,以便其他正在等待此锁的线程可以得到同步锁并运行,只有其他线程调用了notify方法(notify并不释放锁,只是告诉调用过wait方法的线程可以去参与获得锁的竞争了,但不是马上得到锁,因为锁还在别人手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后才会释放锁,可以在notfiy方法后增加一个等待和一些代码,看看效果),调用wait方法的线程就会解除wait状态和程序可以再次得到锁后继续向下运行。

3 面试提示

对于wait的讲解一定要配合例子代码来说明,才显得自己真明白。

十二 String、StringBuffer和StringBuilder的区别

1 概念

1.String

字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。用于存放字符的数组被声明为final的,因此只能赋值一次,不可再更改。

2 StringBuffer

字符串变量(Synchronized,即线程安全)。如果要频繁对字符串内容进行修改,出于效率考虑最好使用StringBuffer,如果想转成String类型,可以调用StringBuffer的toString()方法。 Java.lang.StringBuffer线程安全的可变字符序列。在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。 StringBuffer上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。

3. StringBuilder

StringBuilder:字符串变量(非线程安全)。在内部,StringBuilder对象被当作是一个包含字符序列的变长数组。 java.lang.StringBuilder是一个可变的字符序列,是JDK5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。 其构造方法如下:
构造方法 描述
StringBuilder() 创建一个容量为16的StringBuilder对象(16个空元素)
StringBuilder(CharSequence cs) 创建一个包含cs的StringBuilder对象,末尾附加16个空元素
StringBuilder(int initCapacity) 创建一个容量为initCapacity的StringBuilder对象
StringBuilder(String s) 创建一个包含s的StringBuilder对象,末尾附加16个空元素

在大部分情况下,效率:StringBuilder > StringBuffer。这主要是由于前者不需要考虑线程安全。

2 三者区别

String类型和StringBuffer的主要性能区别:

String是不可变的对象, 因此在每次对String 类型进行改变的时候,都会生成一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,性能就会降低。 使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象并改变对象引用。所以多数情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。 在某些特别情况下, String 对象的字符串拼接其实是被 Java Compiler 编译成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,例如:String s1 = “This is only a” + “ simple” + “ test”; StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”); 生成 String s1对象的速度并不比 StringBuffer慢。其实在Java Compiler里,自动做了如下转换: Java Compiler直接把上述第一条语句编译为:String s1 = “This is only a simple test”; 所以速度很快。但要注意的是,如果拼接的字符串来自另外的String对象的话,Java Compiler就不会自动转换了,速度也就没那么快了,例如:String s2 = “This is only a”; String s3 = “ simple”; String s4 = “ test”; String s1 = s2 + s3 + s4; 这时候,Java Compiler会规规矩矩的按照原来的方式去做,String的concatenation(即+)操作利用了StringBuilder(或StringBuffer)的append方法实现,此时,对于上述情况,若s2,s3,s4采用String定义,拼接时需要额外创建一个StringBuffer(或StringBuilder),之后将StringBuffer转换为String;若采用StringBuffer(或StringBuilder),则不需额外创建StringBuffer。

3 使用策略

(1)**基本原则**:如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer。(2)**不要使用String类的"+"来进行频繁的拼接**,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则.(3)为了获得更好的性能,在构造 StringBuffer 或 StringBuilder 时应 **尽可能指定它们的容量** 。当然,如果你操作的字符串长度(length)不超过 16 个字符就不用了,当不指定容量(capacity)时默认构造一个容量为16的对象。不指定容量会显著降低性能。(5)相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在 StringBuffer 上,并且**确定你的模块不会运行在多线程模式下**,才可以采用StringBuilder;否则还是用StringBuffer。(6) String覆盖了equals方法和hashCode方法,而其他两个没有,因此放入java集合中会出现问题

十三、Iterator和ListIterator的区别

ListIterator有add()方法,可以向List中添加对象,而Iterator不能

ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasprevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。

ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。

都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表