Java基础

Java基础

String、StringBuffer、StringBuilder:三者异同?

答:底层存储jdk9开始从char[]数组变成byte[]数组;

String:不可变字符序列,声明为fianl,不可扩容,效率最低;因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后,JVM的GC就会开始工作,那速度是一定会相当慢的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lWQUpT1j-1618844315047)(C:\Users\jin\AppData\Roaming\Typora\typora-user-images\image-20210318132256063.png)]

StringBuffer:可变字符序列,可扩容,线程安全,效率低;

StringBuilder(jdk5.0):可变字符序列,可扩容,线程不安全,效率高;

​ 对象能够被多次的修改,并且不产生新的未使用对象

类继承关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gPvxMXFh-1618844315051)(C:\Users\jin\AppData\Roaming\Typora\typora-user-images\image-20210318133046631.png)]

区别:
  • 如果操作少量的数据使用String;
  • 多线程操作字符串缓冲区下操作大量数据StringBuffer
  • 单线程操作字符串缓冲区操作大量数据StringBuilder

​ String初始化时可以赋空值;StringBuffer不行;

  • 字符串拼接时:

    String S1 = “This is only a” + " simple" + " test";
    StringBuffer Sb = new StringBuffer(“This is only a”).append(" simple").append(" test");

    String远大于StringBuffer,因为JVM将"This is only a" + " simple" + " test"看成“This is only a simple test”;

    若换成String S1 = S2 +S3 + S4;则速度就没StringBuffer快了;

    StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

    StringBuffer、StringBuilder初始化底层数组长度为:字符串长度+16

    扩容机制:x2+2

== 和 equals()的区别?

equals():直接继承Object中的equals()方法时,比较的是两个引用是否指向的是同一个对象;

==: 对于基本类型比较的是值,对于引用类型比较的是引用地址;

hashCode()和equals()的区别?

  • equals相等,hashcode不一定相等;

    若equals方法未重写,则比较的是堆中地址,相等则是同一个对象,hashcode不管重写不重写都相等;

    若equals方法重写,比较的是对象的成员变量值,equals相等有可能是队中new了一个对象,地址不相同;

  • hashcode相等,equals不一定相等;

    若未重写,代表的是一个地址,那么就是同一个对象,equals不管是否重写都相等;

    若重写,代表的是成员变量的hashcode值,但是像HashMap集合相同的hashcode值,其值不一定相同,因为它是数组+链表+红黑树的存储结构;

String str=“donkey” 与 String str=new String(“donkey”) 一样吗?

答:不一样;因为内存的分配方式不一样。前者,Java虚拟机将其分配到常量池中;后者,Java虚拟机将其分到堆内存中,在内存中开辟一块新的地址用来存放它。

String s = new String(“xyz”);创建几个String Object?

答:一个或两个;若常量池中存在”xyz“,只在new操作时,在堆中开辟了一个对象,引用常量池中的对象;若不存在,在“=”操作时,常量池中创建一个字符串对象,“new”操作时,堆中创建一个对象,引用该字符串对象;

final, finally, finalize的区别?

final:常用来修饰属性,方法,类;属性不可更改,方法不可被覆盖,类不可被继承;

finally:异常中的关键字,在方法中出现时,无论异常是否出现都会执行其代码块;

finalize:是Java垃圾回收机制中的一个方法,重写其方法可回收其他资源,如文件关闭;

​ (JVM不保证此方法总被调用一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。)

JVM运行原理

JVM编译

​ 将Java问价经过一次编译后,Java代码编译成Java字节码文件(.class),然后可以在任意安装了对应的JVM平台上运行,这就是一次编译,到处运行

附:https://www.cnblogs.com/whhjava/p/9916626.html

类加载机制

​ 分为七步:加载(loading)-> 验证(Verification)-> 准备(Preparation)-> 解析(Resolution)-> 初始化 (Initialization)-> 使用(Using)-> 卸载(Unloading)

​ 第一步:加载;获取二进制字节流(class文件);将静态的存储节后转换为方法区中的运行时数据结构;生成一个对象放入到Java堆中,做为对方法区的引用;

​ 第二步:验证;class文件的表示:版本号、每个部分是否正确(字段表、方发表等)、验证常量池(常量类型、数据结构等是否正确,UTF-8是否正确),元数据验证(父类验证、继承验证、final验证),字节码验证,符号引用验证,若有错误出现,则验证失败;

​ 第三步:准备;为类变量分配内存和设置类变量初始化。此过程,只针对static类变量进行内存分配,未赋值,所有的类变量都是初始化值;如果是final,会直接对应到常量池中,直接赋值;

​ 第四步:解析;对符号引用进行解析,将符号引用解析为直接引用(指向目标的指针或偏移量),主要是类、接口、字段、方法等。

​ 第五步:初始化;执行方法的过程,对静态代码块进行初始化,对类进行初始化;

​ 第六步:使用;使用class文件

​ 第七步:卸载;不在使用时,卸载class文件;

JDk JRE JVM :

JDK是开发工具包,JRE是包括JVM,JRE有运行.class文件的java.exe;

JVM是Java虚拟机,JVM在执行字节码时,把字节码解释成具体平台的机器指令执行,”一次编译,到处运行“

JDK下的jre文件夹下有俩个文件夹lib和bin;在这里可以理解为bin就是jvm,lib就是类库;所以JRE=JVM+类库

IO流

streams是一组有顺序的,有起点和终点的字节集合,是数据传输的总称。数据传输

分类

数据流向:输入流、输出流

数据类型:字节流、字符流

字节流:InputStream和OutputStream,每次读写一个字节,直接连接到输入源的流;

	InputStream :
				FileInputStream
				BufferedInputStream
				DataInputStream
				ObjectInputStream
	OutputStream:
					FileOutputStream
					BufferedOutputStream
					DataOutputStream
					ObjectOutputStream

字符流:Reader和Writer以字符为单位进行数据处理的IO流。本质是居于字节流读取时,去查找指定的码表;

	Reader:
        InputStreamReader
        FileReader
        BufferedReader
    Writer:
        OutputStreamWriter
        FileWriter
        BufferedWriter

IO流模型:BIO,NIO,AIO

同步:用户进程触发IO操作并等待或轮询的去看IO操作是否就绪

异步:用户进程触发IO操作以后便开始做自己的事情,当IO操作完成的时候会得到IO完成的通知;

阻塞:所谓阻塞方式,当试图对该文件描述进行读写时,如果当时没有东西可读,或者暂时不可写,程序就进入等待状态

非阻塞:如果没东西可读或不可写,读写函数马上返回,而不会等待

同步阻塞IO(BIO):服务器实现模式为一个链接一个线程,即客户端有连接请求时服务器就启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善;

编程实现:BIO是同步阻塞IO流,每个获取的连接都需要创建一个新的处理线程

同步非阻塞IO(NIO):服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。用户线程也需要不时的询问IO操作是否就绪,这就要求用户进程不停的去询问;

编程实现:jdk1.4开始实现;

工作原理:
由一个专门的线程来处理所有的IO事件,并负责分发;
事件驱动机制:事件到的时候触发,而不是同步的去监视事件;
线程通讯:线程之间通过wait和notify等方式通讯。保证每次上下文切换都是有意义的。减少无谓的线程切换;
服务端和客户端都各自维护一个管理通道的对象(selector),该对象能检测一个或多个通道(channel)上的事件;
以服务器为例:如果服务端的selector上注册了读事件,某时刻客户端给服务端发送一些数据,阻塞IO这时会调用;
read()方法阻塞读取数据,而NIO的服务端会在selector中添加一个读事件。服务端的处理线程会轮询地访问selector;
如果访问selector时发现有感兴趣的事件到达,则会处理这些事件,如果没有则处理线程会一直阻塞直到感兴趣的事件到达;

异步阻塞IO(AIO):用户进程只需要发起一个IO操作然后立即返回,等IO操作真正完成以后,应用程序会得到通知,此时用户进程只需要对数据进行处理就好,不需要进行实际的IO读写操作,因为真正的IO读写或者写入操作已由内核完成;

编程实现:jdk1.7开始实现,实现了真正的异步非阻塞,将所有的IO都交给操作系统处理 ,当IO事件触发时,回调用户的Handle即可

面向对象

面向对象的三大重要特征:封装、继承、多态
面向对象:

把构成问题的事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事务在整个解决问题的步骤中的行为。

声明周期

​ 面向对象的分析:OOA

​ 设计:OOD

​ 编程:OOP

​ 优点:耦合度低,扩展力强,更容易解决现实世界当中更复杂的业务逻辑;

​ 缺点:性能比面向过程低;

封装

​ 封装的某些信息隐藏在类内部,不允许外部直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问;

封装步骤:

​ 1)、所有属性私有化,使用private修饰,只允许在本类中访问;

​ 2)、提供get和set方法

​ ps:static修饰的方法调用:类名.方法名(实参)

​ 没有static修饰的方法 调用:引用.方法名(实参)

​ public:访问在同一个class path下的所有类、接口;

​ protected:本包的类和子类;

​ default:本包的类;

​ private:本类内部;

构造方法

​ 语法结构:

​ [修饰符列表]构造方法名(形参列表){
​ 构造方法体
​ }

​ 普通方法:

​ [修饰符列表] 返回值类型 方法名(形参列表){
​ 方法体
​ }

​ 1)、对于构造方法来说,构造方法名必须与类列保持一致;
​ 2)、构造方法的作用:通过构造方法的调用,可以创建对象
​ 3)、构造方法调用:
​ new 构造方法名(实参列表);
​ 普通方法的调用:
​ 方法修饰符中有static时,类名.方法名(实参列表);
​ 方法修饰符中没有static时,引用.方法名(实参列表);

继承

​ 从已有的类中派生新的类,新类拥有旧类的数据属性和行为,并能扩展新的能力。

​ 语法结构:
​ B extnds A
​ ps:私有属性和方法不能被继承。
​ final:修饰类,不能被继承;修饰方法,不允许被重写;修饰属性,必须有值,初始化后不能被修改。
​ super:访问的是父类的属性和方法
​ this:保证了内存地址指向自身,this存储在JVM堆内存Java对象内部,每一个对象都有其对应的this。
​ 子类可以拥有自己的属性和方法;可以用自己的方式实现父类的方法和属性(重写)
​ 通过extends关键字实现类于类之间的继承;任何类都可以被用作父类,不管是否为抽象类;
​ 一个父类被多个子类继承,但一个子类只能继承一个父类。与接口不同的是,可以实现多个接口。

多态

​ 指允许不同类的对象对同一消息做出响应,即同一响应可以根据发送对象的不同而采用多种不同的行为方式;
​ 实现多态称为动态绑定:指在执行期间判断所引用对象的实例类型,根据实际的类型调用其相应的方法。
​ 作用:消除类型之间的耦合关系。
​ 多态的必要条件:
​ 1)、有继承;
​ 2)、有方法重写
​ 3)、父类引用指向子类对象

重载(overload)

同一个类中、方法名相同、参数列表不同:类型、顺序、个数;与返回值类型无关,与修饰符列表无关;

重写(override)

​ 在子类与父类中,父类方法无法满足子类的业务需求;

​ 返回值类型相同、方法名相同、形参列表相同;

​ 访问权限不能低于父类、抛出的异常更少;

​ 私有方法不能继承,不能重写;

​ 构造方法不能继承,不能重写;

​ 重写只发生在方法中,不针对属性。

抽象类

​ 在普通类的结构里增加了抽象方法的组成部分;

​ 抽象方法:没有方法体的方法,即没有{},同时还需要使用abstract修饰;

​ 有抽象方法的类是抽象类,抽象类要使用abstract关键字声明;
​ 抽象类不能直接实例化,当一个类实例化后,可以调用类中的属性,而抽象方法没有方法体,则无法进行调用。
​ 抽象类使用原则:
​ 1)、抽象方法必须为publish或protected,默认为publish
​ 2)、抽象列不能直接实例化,需要依靠子类采用向上转型的方式处理;
​ 3)、必须有子类
​ 4)、子类必须覆写抽象类中的全部抽象方法,若没有实现父类的抽象方法,则子类也定义为abstract类。

类加载顺序

​ 父类静态变量;
​ 父类静态代码块;
​ 子类静态变量;
​ 子类静态代码块;
​ 父类非静态变量;
​ 父类构造函数;
​ 子类非静态变量;
​ 子类构造函数;

计算机网络

TCP三次握手

几个简单概念:

​ 主机A向主机B发送数据的同时,主机A也可以接收主机B发过来的数据;
​ 在TCP报文包里,有六个标志位 ,这里了介绍其中的两个:SYN包与ACK包;
​ SYN包:请求建立连接的数据包,SYN=1,则表示要建立连接;
​ ACK包:回应数据包(用来做回应的)表示接收到了对方的某个数据包,仅当ACK=1时确认号字段才有效;
​ seq序列号:用来标记数据包的顺序;
​ ack确认号:表示序号为确认号减去1的数据包及其以前的所有数据包已经正确接收,也就是说他相当于下一个准备接收的字节的序号 (如果ack确认号是101,则表示前100个都已经收到了);
​ 当我们发一个SYN=1的包时,会得到一个ACK=1的包;

三次握手

​ 第一次握手:建立连接时,客户端发送数据包,标志位SYN=1,随机seq=x到服务器(x代表随机生成的数)
​ 第二次握手:服务器收到SYN=1的包,知道客户端要建立连接,返回SYN=1和ACK=1,ack=x+1,和随机seq=y (y代表随机生成的数)
​ 第三次握手:客户端厚道服务器的SYN+ACK包,向服务器发送确认包ACK=1,ack=y+1

WEB

Get和Post

​ get把参数包含在URL中,POST通过request body传递参数
​ get比post更不安全,因为参数直接暴露在url上
​ get在浏览器回退时是无害的,而post会再次提交请求
​ GET在浏览器回退时是无害的,而POST会再次提交请求。
​ GET产生的URL地址可以被Bookmark,而POST不可以。
​ GET请求会被浏览器主动cache,而POST不会,除非手动设置。
​ GET请求只能进行url编码,而POST支持多种编码方式。
​ GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
​ GET请求在URL中传送的参数是有长度限制的,而POST么有。
​ 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
​ 传文件、form表单等必须是post

Session与Cookie

​ session存在服务器里,客户端不知道其中的信息;cookie存在客户端,服务器能够知道其中的信息
​ session中保存的是对象,cookie里保存的是字符串;
​ session不能区分路径,同一个用户在访问同一个网站期间,所有的session在任何一个地方都可以读取到; 而cookie如果设置了路径参数,那么同一个网站中不同路径下的cookie是互相访问不到的;
​ session需要借助cookie才能正常生效,如果客户端禁止cookie的话,session将失效;

类与接口

类是单继承,多实现;接口不能实现另一个接口,只能继承该接口,且可以多继承。

Split()
String str = "";
System.out.println(str.split(",").length);

解释:length()方法是用在String类型上获得其长度;length方法是用在**String[]**类型上求其长度;

多线程

状态

​ 运行、就绪、挂起、结束

进程和线程的关系

进程是一段正在执行的程序;线程是程序执行过程中,能够执行程序代码的一个执行单元;

​ 线程可称为轻量级进程,是程序执行的最小单元;

​ 一个进程可以有多个线程,各个线程之间共享程序的内存空间(代码段、数据段、堆空间)以及一些进程级的资源,但也拥有属于自己的堆空间;

为什么要使用多线程

  • 使用多线程可以减少程序的响应时间;
  • 与进程相比,线程的创建和切换开销较小;
  • 使用多线程能简化程序的结构;

解释:length()方法是用在String类型上获得其长度;length方法是用在String[]类型上求其长度;

多线程

状态

​ 运行、就绪、挂起、结束

进程和线程的关系

进程是一段正在执行的程序;线程是程序执行过程中,能够执行程序代码的一个执行单元;

​ 线程可称为轻量级进程,是程序执行的最小单元;

​ 一个进程可以有多个线程,各个线程之间共享程序的内存空间(代码段、数据段、堆空间)以及一些进程级的资源,但也拥有属于自己的堆空间;

为什么要使用多线程

  • 使用多线程可以减少程序的响应时间;
  • 与进程相比,线程的创建和切换开销较小;
  • 使用多线程能简化程序的结构;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值