下面是我最近遇到的一些还不清楚的问题,有的是做题过程中的错误,有的是一些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攻击;
举个例子:如下五子棋的一个游戏,用面向过程的设计思路为:开始游戏、白子先走,黑子走,判断输赢,游戏结束…… ;而对于面向对象的设计思路:整个游戏可以分为:黑白双方(两方行为都是一样的),棋盘系统(负责绘制画面),规则系统(设置游戏规则,判断输赢等)
(1)简单性(简单易学)
(2)面向对象(封装,继承,多态)
(3)平台无关性(Java虚拟机实现了java程序的平台无关性)
(4)可靠性
(5)安全性
(6)支持多线程(C++语言没有内置的多线程机制,而是调用操作系统多线程功能来进行多线程的设计,而Java语言提供了多线程支持)
(7)支持网络编程而且很方便
(8)编译与解释并存
Java和C++都是面向对象语言,都支持封装、继承和多态;
Java不提供指针来直接访问内存,程序内存更加安全;
Java的类是单继承的,C++支持多重继承;虽然Java的类只能单继承,但是接口可以实现多继承。
Java有自动内存管理机制,不需要程序员手动释放内存。
在继承中学到,父类的私有属性和构造方法不能被覆写,所有Constructor不能被override(覆写),但是可以overload(重载)
由于静态方法可以不通过对象直接调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问其他非静态变量成员。
Java里面一切都是对象,是对象的话,字符串肯定就有长度,即然有长度,编译器就可以确定要输出的字符个数,当然也就没有必要去浪费那1字节的空间用以标明字符串的结束了。
封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构。同时也保护了数据,数据被保护在抽象数据类型的内部,尽可能的隐藏内部细节,只保留一些对外接口使之与外部发生联系,因此对外部而言,类的内部方法是隐藏的,暴露在外部的只是它的访问方法;举例子:汽车和发动机(看得见的只是汽车的外壳,看不见发动机)
对于封装而言,一个对象它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作,使用封装有四大好处:
继承是为了重用父类代码,若两个类属于is - a 关系(比如:狗类和动物类 狗 is a 动物)就可以用继承关系。使用了继承关系的类有一种特殊的功能,就是可以在不改变父类代码的情况下对父类的功能进行扩充。
多态顾名思义就是一种形式多种状态。所谓的多态在程序中的表现就是程序中引用的变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才能确定,即一个引用变量到底会指向那个类的实例对象,该引用变量发出的方法到底是那个类中实现的方法,必须在程序运行期间才能决定,,因为在程序运行时才能确定具体的类。这样就可以在不用修改源程序的情况下,就可以让引用变量绑定到各个不同的类的实例上,从而导致该引用调用的具体方法随之改变,即可以不修改源代码就可以改变程序运行时绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
举个例子:比如你是一个酒神,对酒情有独钟,有一天你回家发现桌子上放了几个杯子里面全装了酒,从外表看你可能分不出哪一杯装的是什么酒,只有喝了才能知道。比如可以这样描述:
酒a = 剑南春;
酒b = 五粮液;
酒c = 酒鬼酒;
这里就是酒的多态性,剑南春,五粮液,酒鬼酒都是酒的字类,我们只是通过酒这一个父类来引用不同的子类,这就是多态。
刚开始看见这个错误我也不知道是为什么,后来通过在网上查了一下,这个就是子类调用父类的无参构造,但是父类中没有写无参构造,所以导致了这个错误。但是从代码中也能看出,我并没有调用父类的无参构造。接下来我通过自己测试,发现其实我们都知道在写继承时,子类构造方法中要调用父类构造方法,但是像下面这个代码,我在子类中没有调用父类构造方法也没报错:
其实是因为如果我们在子类构造方法中没有主动的调用父类构造方法,编译器会自动调用父类的无参构造,在刚刚那段出错的代码中,由于我在父类中写了有参构造,编译器就不会自动生成一个默认的无参构造,所以此时父类中只有一个有参构造,而编译器会默认调用父类的无参构造,所以就会出错。
解决方法:可以在父类中手动加上无参构造,或者在子类中手动调用有参构造,这样编译器就不会再自动调用不存在的无参构造了。
在写题的过程中,我在这也遇到过一次坑,主要是因为对ArrayList中的方法不熟悉。
其中:
要删除 ArrayList
应该是 : remove (new Integer (n));
如果是: remove (n),表示删除的是下标为n的元素
例子如下:
运行结果:
java语言使用在字符集是16位的Unicode编码。
对于任意二叉树,如果其叶子结点的个数为n0, 杜度为二的非叶节点个数为n2,则有:n0 = n2+1;
这是一个基于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洪水攻击)。
网络延迟:在传输介质中传输所用的时间,即从报文开始进入网络到它开始离开网络之间的时间。
(后面遇到在继续补充 ……)