Java

比较一下java和c++的语言特点

(自动内存管理,多继承,多继承设计有什么缺点,移植性,条件编译,tcp字节序)
Java是解释性语言,C++是编译性语言,C++会更快一点

Java为什么安全

很多,就语言本身来讲,体现在严格遵循面向对象的规范、无指针运算、数组边界检查、强制类型转换检查等。
就广义的Java概念来讲,Java的安全模型被分为三个主要的防范区域:
Byte-code验证器、类装载器和安全管理器。
(重要是去掉了指针,以及代码安全性检测和垃圾回收 机制,别小看这个代码检测,相当严格的,c中会出现的错误但是能编译通过的在java里不行,如果用eclipse编程直接就会提示哪里有误,个人觉得那个异常处理机制不错)

Java的四个基本特性(抽象、封装、继承,多态)

抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
继承:子类继承父类的属性和行为,并能根据自己的需求扩展出新的属性和行为,提高了代码的可复用性。
封装:把对象的属性和方法结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。
多态:是相同的操作、函数或过程,可以作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果。

多态的理解(多态的实现方式)

方法重载(overload)实现的是编译时的多态性(静态绑定)。
方法重写(override)实现的是运行时的多态性(动态绑定)。运行时的多态是面向对象最精髓的东西。
要实现多态需要做两件事:
方法重写(子类继承父类并重写父类中已有的或抽象的方法);
对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。

面向对象和面向过程的区别?

面向过程”是一种是事件为中心的编程思想。就是分析出解决问题所需的步骤,然后用函数把这些步骤实现,并按顺序调用。

面向对象是以“对象”为中心的编程思想。

简单的举个例子:汽车发动、汽车到站

“面向过程”是两个事件,汽车启动是一个事件,汽车到站是另一个事件。

关心的是汽车这类对象,两个事件是对象的行为,两个行为的顺序没有强制要求。

重载和重写,如何确定调用哪个函数

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

重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类;如果父类方法访问修饰符为private则子类中就不是重写。

构造器Constructor是否可被override

构造器不能被重写,不能用static修饰构造器,只能用 public private protected这三个权限修饰符,且不能有返回语句。

static和final的区别和用途

声明为final的方法不能被重写。声明为static的方法不能被重写,但是能够被再次声明。

static修饰的成员变量和方法,从属于类。

Static

修饰变量:静态变量随着类加载时被完成初始化,内存中只有一个,且JVM也只会为它分配一次内存,所有类共享静态变量。

修饰方法:在类加载的时候就存在,不依赖任何实例;static方法必须实现,不能用abstract修饰。

修饰代码块:在类加载完之后就会执行代码块中的内容。

父类静态代码块->子类静态代码块->父类非静态代码块->父类构造方法->子类非静态代码块->子类构造方法

Final

修饰变量:

编译期常量:类加载的过程完成初始化,编译后带入到任何计算式中。只能是基本类型。

运行时常量:基本数据类型或引用数据类型。引用不可变,但引用的对象内容可变。

修饰方法:不能被继承,不能被子类修改。

修饰类:不能被继承。

修饰形参:final形参不可变

HashMap和Hash Table的区别,Hash Map中的key可以是任何对象或数据类型吗?HashTable是线程安全的么?

HashMap和Hash Table的区别

Hashtable的方法是同步的,HashMap未经同步,所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样。
Hashtable不允许 null 值(key 和 value 都不可以),HashMap允许 null 值(key和value都可以)。
两者的遍历方式大同小异,Hashtable仅仅比HashMap多一个elements方法。
Hashtable 和 HashMap 都能通过values()方法返回一个 Collection ,然后进行遍历处理。
两者也都可以通过 entrySet() 方法返回一个 Set , 然后进行遍历处理。
HashTable使用Enumeration,HashMap使用Iterator。
哈希值的使用不同,Hashtable直接使用对象的hashCode。而HashMap重新计算hash值,而且用于代替求模。
Hashtable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
HashTable基于Dictionary类,而HashMap基于AbstractMap类
Hash Map中的key可以是任何对象或数据类型吗
可以为null,但不能是可变对象,如果是可变对象的话,对象中的属性改变,则对象HashCode也进行相应的改变,导致下次无法查找到已存在Map中的数据。
如果可变对象在HashMap中被用作键,那就要小心在改变对象状态的时候,不要改变它的哈希值了。我们只需要保证成员变量的改变能保证该对象的哈希值不变即可。

HashTable是线程安全的么

HashTable是线程安全的,其实现是在对应的方法上添加了synchronized关键字进行修饰,由于在执行此方法的时候需要获得对象锁,则执行起来比较慢。所以现在如果为了保证线程安全的话,使用CurrentHasxhMap。

HashMap和Concurrent HashMap区别, Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全?

HashMap和Concurrent HashMap区别?

HashMap是非线程安全的,CurrentHashMap是线程安全的。
ConcurrentHashMap将整个Hash桶进行了分段segment,也就是将这个大的数组分成了几个小的片段segment,而且每个小的片段segment上面都有锁存在,那么在插入元素的时候就需要先找到应该插入到哪一个片段segment,然后再在这个片段上面进行插入,而且这里还需要获取segment锁。
ConcurrentHashMap让锁的粒度更精细一些,并发性能更好。

Concurrent HashMap 线程安全吗, Concurrent HashMap如何保证 线程安全?

HashTable容器在竞争激烈的并发环境下表现出效率低下的原因是所有访问HashTable的线程都必须竞争同一把锁,那假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。
get操作的高效之处在于整个get过程不需要加锁,除非读到的值是空的才会加锁重读。get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。定义成volatile的变量,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被多线程写,就是写入的值不依赖于原值),在get操作里只需要读不需要写共享变量count和value,所以可以不用加锁。
Put方法首先定位到Segment,然后在Segment里进行插入操作。插入操作需要经历两个步骤,第一步判断是否需要对Segment里的HashEntry数组进行扩容,第二步定位添加元素的位置然后放在HashEntry数组里。

因为别人知道源码怎么实现的,故意构造相同的hash的字符串进行攻击,怎么处理?那jdk7怎么办?

怎么处理构造相同hash的字符串进行攻击?
当客户端提交一个请求并附带参数的时候,web应用服务器会把我们的参数转化成一个HashMap存储,这个HashMap的逻辑结构如下:key1–>value1;
但是物理存储结构是不同的,key值会被转化成Hashcode,这个hashcode有会被转成数组的下标:0–>value1;
不同的string就会产生相同hashcode而导致碰撞,碰撞后的物理存储结构可能如下:0–>value1–>value2;
1、限制post和get的参数个数,越少越好
2、限制post数据包的大小
3、WAF
Jdk7 如何处理hashcode字符串攻击
HashMap会动态的使用一个专门的treemap实现来替换掉它。

String、StringBuffer、StringBuilder以及对String不变性的理解

String、StringBuffer、StringBuilder都是 final 类, 都不允许被继承;
String 长度是不可变的, StringBuffer、StringBuilder 长度是可变的;
StringBuffer 是线程安全的, StringBuilder 不是线程安全的,但它们两个中的所有方法都是相同的,StringBuffer在StringBuilder的方法之上添加了synchronized修饰,保证线程安全。
StringBuilder比StringBuffer拥有更好的性能。
如果一个String类型的字符串,在编译时就可以确定是一个字符串常量,则编译完成之后,字符串会自动拼接成一个常量。此时String的速度比StringBuffer和StringBuilder的性能好的多。
String不变性的理解
String 类是被final进行修饰的,不能被继承。
在用+号链接字符串的时候会创建新的字符串。
String s = new String(“Hello world”); 可能创建两个对象也可能创建一个对象。如果静态区中有“Hello world”字符串常量对象的话,则仅仅在堆中创建一个对象。如果静态区中没有“Hello world”对象,则堆上和静态区中都需要创建对象。
在 java 中, 通过使用 “+” 符号来串联字符串的时候, 实际上底层会转成通过 StringBuilder 实例的 append() 方法来实现。
String有重写Object的hashcode和toString吗?如果重写equals不重写hashcode会出现什么问题?

String有重写Object的hashcode和toString吗?

String重写了Object类的hashcode和toString方法。
当equals方法被重写时,通常有必要重写hashCode方法,以维护hashCode方法的常规协定,该协定声明相对等的两个对象必须有相同的hashCode
object1.euqal(object2)时为true, object1.hashCode() == object2.hashCode() 为true
object1.hashCode() == object2.hashCode() 为false时,object1.euqal(object2)必定为false
object1.hashCode() == object2.hashCode() 为true时,但object1.euqal(object2)不一定定为true
重写equals不重写hashcode会出现什么问题
在存储散列集合时(如Set类),如果原对象.equals(新对象),但没有对hashCode重写,即两个对象拥有不同的hashCode,则在集合中将会存储两个值相同的对象,从而导致混淆。因此在重写equals方法时,必须重写hashCode方法。

Java是否有内存泄露和内存溢出

静态集合类,使用Set、Vector、HashMap等集合类的时候需要特别注意。当这些类被定义成静态的时候,由于他们的生命周期跟应用程序一样长,这时候就有可能发生内存泄漏。
监听器: 在Java编程中,我们都需要和监听器打交道,通常一个应用中会用到很多监听器,我们会调用一个控件,诸如addXXXListener()等方法来增加监听器,但往往在释放的时候却没有去删除这些监听器,从而增加了内存泄漏的机会。
物理连接:一些物理连接,比如数据库连接和网络连接,除非其显式的关闭了连接,否则是不会自动被GC 回收的。一般情况下,在try代码块里创建连接,在finally里释放连接,就能够避免此类内存泄漏。
内部类和外部模块等的引用:内部类的引用是比较容易遗忘的一种,而且一旦没释放可能导致一系列的后继类对象没有释放。在调用外部模块的时候,也应该注意防止内存泄漏,如果模块A调用了外部模块B的一个方法,如:
public void register(Object o)
这个方法有可能就使得A模块持有传入对象的引用,这时候需要查看B模块是否提供了出去引用的方法,这种情况容易忽略,而且发生内存泄漏的话,还比较难察觉。
单例模式:因为单利对象初始化后将在JVM的整个生命周期内存在,如果它持有一个外部对象的(生命周期比较短)引用,那么这个外部对象就不能被回收,从而导致内存泄漏。如果这个外部对象还持有其他对象的引用,那么内存泄漏更严重。

匿名内部类是什么?如何访问在其外面定义的变量?

匿名内部类是什么?

匿名内部类是没有访问修饰符的。
所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final
匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。

如何访问在其外面定义的变量?

所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final
如果你定义一个类,包括学号,姓名,分数,如何把这个对象作为key?要重写equals和hashcode吗
需要重写equals方法和hashcode,必须保证对象的属性改变时,其hashcode不能改变。

为什么要实现内存模型?

内存模型的就是为了在现代计算机平台中保证程序可以正确性的执行,但是不同的平台实现是不同的。
编译器中生成的指令顺序, 可以与源代码中的顺序不同;
编译器可能把变量保存在寄存器而不是内存中;
处理器可以采用乱序或并行等方式来执行指令;
缓存可能会改变将写入变量提交到主内存的次序;
保存在处理器本地缓存中的值,对其他处理器是不可见的;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值