Java中常见问题总结

下面是我最近遇到的一些还不清楚的问题,有的是做题过程中的错误,有的是一些java基础方面的问题,我把这些做了一个总结,避免以后在犯,也可以给和我一样Java入门的人参考,如果有总结的不对的地方,欢迎大家可以给我提出来~~~

目录

 

一、Java一些基础方面的问题

1、面向对象和面向过程的区别:

2、Java语言的特点:

3、关于JVM,JDK,JRE

4、Java和C++的区别:

5、String、StringBuffer和StringBuilder的区别是什么?String为什么是不可变的?这三种字符串的适用场景是什么?

三者之间的区别

为什么String不可变

适用场景

6、构造方法能否被覆写:

7、方法重写和重载的区别:

8、在一个静态方法中调用一个非静态成员为什么是非法的?

9、Java中的字符串,字符数组为什么没有结束标志

10、Java中面向对象的三大特性:封装,继承,多态

封装

继承

多态

二、刷题过程中遇到的问题

1、There is no default constructor available in “父类”

2.ArrayList中的remove方法:remove (int index) 和 remove(Object obj)

3、Java语言使用的字符集是:Unicode

4、某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( 200个)

5、什么是synflood攻击;

 

 

一、Java一些基础方面的问题

1、面向对象和面向过程的区别:

  • 面向过程:面向过程就是分析出解决一个问题所需要的步骤,然后利用函数把这些步骤一步一步的实现,使用的时候只需要一个方法一个方法的调用就可以了。
    • 优点:性能比面向对象高,因为面向对象中类调用时需要实例化,开销比较大,消耗资源比较大
    • 缺点:没有面向对象那样容易维护、复用和扩展
  • 面向对象:面向对象是把一个问题的组成分解为一个个的对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。
    • 优点:易维护,易复用,易扩展。由于面向对象具有封装、继承、多态的特性,可以设计出低耦合系统,使系统更加灵活,容易维护
    • 缺点:性能比面向过程低。

举个例子:如下五子棋的一个游戏,用面向过程的设计思路为:开始游戏、白子先走,黑子走,判断输赢,游戏结束…… ;而对于面向对象的设计思路:整个游戏可以分为:黑白双方(两方行为都是一样的),棋盘系统(负责绘制画面),规则系统(设置游戏规则,判断输赢等)

2、Java语言的特点:

(1)简单性(简单易学)

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

(3)平台无关性(Java虚拟机实现了java程序的平台无关性)

(4)可靠性

(5)安全性

(6)支持多线程(C++语言没有内置的多线程机制,而是调用操作系统多线程功能来进行多线程的设计,而Java语言提供了多线程支持)

(7)支持网络编程而且很方便

(8)编译与解释并存

3、关于JVM,JDK,JRE

  • JVM:JVM是运行Java字节码(.class文件)的虚拟机,不同的操作系统中有不同的虚拟机,但是这些不同的虚拟机运行相同的字节码会出现相同的结果。字节码和不同系统的JVM虚拟机是实现Java语言“一次编译,随处可运行”的关键所在。
  • JRE(Java Runtime Environment):Java运行时环境,包含了Java虚拟机,Java基础类库,是使用java语言编写的程序运行所需要的软件环境,是提供给想运行java程序的用户使用的。
  • JDK(Java Development Kit):Java开发工具包,是程序员使用java语言编写java程序所需要的开发工具包是提供给程序员使用的,JDK中包含了JRE的全部,同时还包含java源码的编译工具javac还包含很多java程序调试和分析工具等。

4、Java和C++的区别:

Java和C++都是面向对象语言,都支持封装、继承和多态;

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

Java的类是单继承的,C++支持多重继承;虽然Java的类只能单继承,但是接口可以实现多继承。

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

5、String、StringBuffer和StringBuilder的区别是什么?String为什么是不可变的?这三种字符串的适用场景是什么?

三者之间的区别

  • String是字符串常量,是不可变的,所以是线程安全的;
  • AbstractStringBuilder是StringBuilder和StringBuffer的公共父类,定义了一些字符串的常用操作方法,如append(), insert()等;
    • StringBuffer对方法加了synchronized关键字,是线程安全的。
    • StringBuilder没有对方法进行同步操作,是线程不安全的。

为什么String不可变

  • 简单来说,String类中使用了final关键字字符数组保存字符串 private final char  value [ ] ,所以String对象是不可变的。
  • 而StringBuilder和StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder类中,也是使用字符数组保存字符串的,但是没有final修饰 char[ ]   value  ,所以这两个对象是可变的。

适用场景

  • 对于少量数据使用String
  • 大量数据,单线程使用StringBuilder
  • 大量数据,多线程使用StringBuffer

6、构造方法能否被覆写:

在继承中学到,父类的私有属性和构造方法不能被覆写,所有Constructor不能被override(覆写),但是可以overload(重载)

7、方法重写和重载的区别:

  • 方法重载:发生在同一个类,方法名必须,参数列表(参数类型不同,参数个数不同,参数顺序不同),方法返回值和修饰符可以不同。发生在编译时。
  • 方法重写:发生在有继承关系的类中,方法名,参数列表必须相同。返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;特别注意:如果父类方法访问权限修饰符为private,子类不能重写该方法。(常在选择题、判断程序输出结果的题中坑新手)

8、在一个静态方法中调用一个非静态成员为什么是非法的?

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

 

9、Java中的字符串,字符数组为什么没有结束标志

Java里面一切都是对象,是对象的话,字符串肯定就有长度,即然有长度,编译器就可以确定要输出的字符个数,当然也就没有必要去浪费那1字节的空间用以标明字符串的结束了。

10、Java中面向对象的三大特性:封装,继承,多态

封装

封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构。同时也保护了数据,数据被保护在抽象数据类型的内部,尽可能的隐藏内部细节,只保留一些对外接口使之与外部发生联系,因此对外部而言,类的内部方法是隐藏的,暴露在外部的只是它的访问方法;举例子:汽车和发动机(看得见的只是汽车的外壳,看不见发动机)

对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作,使用封装有四大好处:

  1. 良好的封装可以减少耦合 ;
  2. 类内部的结构可以自由修改 ;
  3. 可以对成员可以更精确的控制 ;
  4. 隐藏信息,实现细节 ;

继承

继承是为了重用父类代码,若两个类属于is - a 关系(比如:狗类和动物类 狗 is a 动物)就可以用继承关系。使用了继承关系的类有一种特殊的功能,就是可以在不改变父类代码的情况下对父类的功能进行扩充。

多态

多态顾名思义就是一种形式多种状态。所谓的多态在程序中的表现就是程序中引用的变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才能确定,即一个引用变量到底会指向那个类的实例对象,该引用变量发出的方法到底是那个类中实现的方法,必须在程序运行期间才能决定,,因为在程序运行时才能确定具体的类。这样就可以在不用修改源程序的情况下,就可以让引用变量绑定到各个不同的类的实例上,从而导致该引用调用的具体方法随之改变,即可以不修改源代码就可以改变程序运行时绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。

举个例子:比如你是一个酒神,对酒情有独钟,有一天你回家发现桌子上放了几个杯子里面全装了酒,从外表看你可能分不出哪一杯装的是什么酒,只有喝了才能知道。比如可以这样描述:

酒a = 剑南春;

酒b = 五粮液;

酒c = 酒鬼酒;

这里就是酒的多态性,剑南春,五粮液,酒鬼酒都是酒的字类,我们只是通过酒这一个父类来引用不同的子类,这就是多态。

 

二、刷题过程中遇到的问题

 

1、There is no default constructor available in “父类”

刚开始看见这个错误我也不知道是为什么,后来通过在网上查了一下,这个就是子类调用父类的无参构造,但是父类中没有写无参构造,所以导致了这个错误。但是从代码中也能看出,我并没有调用父类的无参构造。接下来我通过自己测试,发现其实我们都知道在写继承时,子类构造方法中要调用父类构造方法,但是像下面这个代码,我在子类中没有调用父类构造方法也没报错:

其实是因为如果我们在子类构造方法中没有主动的调用父类构造方法,编译器会自动调用父类的无参构造,在刚刚那段出错的代码中,由于我在父类中写了有参构造,编译器就不会自动生成一个默认的无参构造,所以此时父类中只有一个有参构造,而编译器会默认调用父类的无参构造,所以就会出错。

解决方法:可以在父类中手动加上无参构造,或者在子类中手动调用有参构造,这样编译器就不会再自动调用不存在的无参构造了。

2.ArrayList中的remove方法:remove (int index) 和 remove(Object obj)

在写题的过程中,我在这也遇到过一次坑,主要是因为对ArrayList中的方法不熟悉。

其中:

  • remove (int index)是移除下标为index的元素;
  • remove (Object obj ) 是移除集合中第一次出现的obj这个指定元素

要删除 ArrayList<Integer> 中的一个整数n时:

应该是 : remove (new Integer (n));

如果是: remove (n),表示删除的是下标为n的元素

例子如下:

运行结果:

 

3、Java语言使用的字符集是:Unicode

java语言使用在字符集是16位的Unicode编码。

4、某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( 200个)

对于任意二叉树,如果其叶子结点的个数为n0, 杜度为二的非叶节点个数为n2,则有:n0 = n2+1;

5、什么是synflood攻击;

这是一个基于TCP的攻击;TCP与UDP不同,它是基于连接的,也就是说:为了在服务端和客户端之间传送TCP数据,必须先建立一个虚拟电路,也就是TCP连接,建立TCP连接的标准过程是这样的:

首先,请求端(客户端)发送一个包含SYN标志的TCP报文,SYN即同步(Synchronize),同步报文会指明客户端使用的端口以及TCP连接的初始序号;

第二步,服务器在收到客户端的SYN报文后,将返回一个SYN+ACK的报文,表示客户端的请求被接受,同时TCP序号被加一,ACK即确认(Acknowledgment)。

第三步,客户端也返回一个确认报文ACK给服务器端,同样TCP序列号被加一,到此一个TCP连接完成。

以上的连接过程在TCP协议中被称为三次握手(Three-way Handshake)。

问题就出在TCP连接的三次握手中,假设一个用户向服务器发送了SYN报文后突然死机或掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器端一般会重试(再次发送SYN+ACK给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为SYN Timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。实际上如果服务器的TCP/IP栈不够强大,最后的结果往往是堆栈溢出崩溃---即使服务器端的系统足够强大,服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇理睬客户的正常请求(毕竟客户端的正常请求比率非常之小),此时从正常客户的角度看来,服务器失去响应,这种情况我们称作:服务器端受到了SYN Flood攻击(SYN洪水攻击)。

6、网络延迟的定义

网络延迟:在传输介质中传输所用的时间,即从报文开始进入网络到它开始离开网络之间的时间。

 

 

(后面遇到在继续补充 ……)

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值