编程过程中必须掌握的理论知识(面试可能用到)

1:关于CHAR与VARCHAR

CHAR是定长的,而VARCHAR是变长的;

假设设置为CHAR(10)或VARCHAR(10),假设存储hello字符串,使用CHAR(10)时,会补上5个空格得到设置值10的长度,如果使用VARCHAR(10)时,则只存储hello,即5个字符。

所以,在实际使用时,如果某列的数据都是固定长度,例如身份证号码固定是18位,则应该使用CHAR(18),如果某列的数据的长度可能不同,例如用户名,每个用户给自己设置的用户名的长度可能不同,则应该使用VARCHAR类型,并约束最大长度,例如20,设置为VARCHAR(20)。

当使用VARCHAR类型时,默认情况下,MySQL会另使用1个字节,用于记录实际存储的字符数,例如设置为VARCHAR(15),且存入helloworld时,实际存入的字符串是10位,则MySQL会另使用1个字节将10记录下来!如果VARCHAR中设置的字符长度更大,且实际存入的字符超过255个,MySQL会自动改为使用2个字节来记录实际存储的字符数,并且,这2个字节就是上限了,所以,最多存入65535个字符。

2:关于UTF-8编码

在Java语言中,使用Unicode编码来表示数据,是最多占2个字节的!在程序运行时,数据是在内存的,根据不同的数据类型可以很好的区分相关的数据,但是,如果数据需要传输到内存以外,例如存储到硬盘中,或者传输到网络中,数据转换为二进制的序列,就无法被接收方正确的处理!

如果需要使用a,它的二进制表示是110 0001(忽略最高位的符号位),假设存在汉字程的二进制是111 0011 1100 1011(假设值),如果需要传输a程a这样的字符串,则实际传输的二进制数是1110 0001 1111 0011 1100 1011 1110 0001,当接收方收到这个数据以后,根本无从判断这到底是2个汉字,还是4个字母,或1字母1汉字1字母,或2字母1汉字、1汉字2字母。

所以,当数据需要传输到内存以外时,必须为这些数据再制定一些特殊的规律,使得接收方能明确的接收相应的数据!

UTF-8就是Unicode的传输编码(Unicode Transfermation Format),这种编码是将Unicode的基础之上添加了特定位数表示特定意义的,以在UTF-8中占2字节为例,二进制序列的格式是:

110 xxxxx 10 xxxxxx
即:只要是UTF-8中占2个字节的字符,第1个字节的前3位都是110,第2个字节的前2位都是10,这几个字节是有特殊意义的,不作为编码位,其中,110中有2个1,表示从这个字节开始,连接的2个字节是1个字符,第2个字节前面的10表示前面的字节并没有完全表示1个字节,当前字节是继续表示同一个字符的。

UTF-8也可能使用3个字节来表示1个字符,当使用3个字节时,其格式是:

1110 xxxx 10 xxxxxx 10 xxxxxx
UTF-8也可能使用4个字节来表示1个字符,当使用4个字节时,其格式是:

11110 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx
所以,UTF-8编码最多可能使用4个字节来表示1个字符,在MySQL中,如果需要表示这种能识别4字节对应1字符的编码方式,需要将编码显式的设置为utf8mb4,否则,默认的utf8表示的是utf8mb3。

3:密码加密

为什么需要加密:防止内部泄密。

密码加密就是将原始密码(明文)使用某些算法进行运算后得到另一个值(密文)的过程!

当用户注册时,就将原始密码进行加密,将密文存储在数据库中,后续,当用户登录,依然将用户登录时输入的原始密码使用同样的规则进行运算,与数据库中的密文进行对比即可!

在处理加密时,一般,并不需要程序员设计加密时使用的算法,而是直接利用现有的算法即可!

所有的加密算法都是不适用于处理密码加密的!因为,所有的加密算法都是可逆的!即:当能够获取加密过程中的所有参数时,就可以根据密文逆向运算得到原文!

如果要对密码进行加密并存储,应该使用消息摘要算法!常见的有MD(Message Digest)系列算法和SHA(Secure Hash Algorithm)家族算法,这类算法的特征:

  1. 原文相同,则摘要数据相同;
  2. 算法不变,则摘要数据的长度不变;
  3. 原文不同,则摘要数据几乎不会相同!

所以,一定存在某些不同的原文,运算得到的摘要结果是相同,这种情况称之为发生了碰撞!消息摘要算法的碰撞概率越低,则越安全,反之,则不安全!例如,王小云教授就曾经将SHA-1算法的碰撞概率研究至2的61(?)次方!并且,王小云教授也找到了MD5的碰撞,但是,并没有直接影响MD5算法的安全性!所以,也有关于“王小云教授破解MD5算法”的报道,但是,不要误以为摘要算法的破解是根据密文逆向运算得到原文!

另外,在网上也有一些网站可以提供“在线破解”,在这些网站中输入摘要结果,就可以得到原文!其实,这些网站是收录了原文与密文的对应关系,记录在数据库中,当需要“破解”/“解密”时,本质上是做数据库查询!所以,如果使用的是这些网站没有收录的原文,则这些网站就“破解”不了对应的密码!

所以,为了保证密码的安全性,可以采取的措施:

  1. 要求用户使用安全强度更高的密码(字符种类、长度);
  2. 多重加密;
  3. 加盐;

使用更长位数的摘要算法(MD系列的都是128位的,SHA系列的有SHA-128、SHA-256、SHA-384、SHA-512,使用commons-codec中的DigestUtils可以实现更多算法的摘要运算);

综合使用以上所有做法!

另外,使用commons-codec中的DigestUtils工具类之前,需要添加依赖:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.13</version>
</dependency>

4:抽象类与接口

第一部分:相似处

都可以包含抽象方法,也可以包括静态常量;

第二部分:语法区别

抽象类中可以有一般的属性,可以有普通的方法,同时,可以有静态常量和抽象方法,不管是属性还是方法,权限修饰符是可以自由设计的;

接口中所有的成员(属性和方法)都是公有的,所有属性都是静态常量,所有方法都是抽象方法(从JDK 1.8开始,允许有默认实现的方法);

一个普通的类,与抽象类的关系是继承(extends)的关系,而与接口的关系是实现(implements)的关系,并且,继承时,只能单继承,而实现时,可以1对多实现;

接口与接口之间也可以继承(extends),并且,是1对多的继承。

第三部分:提高(深层次理解,应用)

抽象类也是一种类,用于描述“类别”,而接口是一种规范、标准,用于描述行为能力、行为模式。

某个类与抽象类的关系可以是is a的关系,即子类是一种父类,例如“猫是一种动物”,而某个类与接口的关系应该是has a的关系,即实现类具有接口描述的行为特征。

5:关于异常

异常的体系结构:

Throwable
    Error
        OutOfMemoryError(OOM)
    Exception
        SQLException
        IOException
            FileNotFoundException
        RuntimeException
            NullPointerException
            ClassCastException
            ArithmeticException
            IndexOutOfBoundsException
                ArrayIndexOutOfBoundsException
                StringIndexOutOfBoundsException

在以上分支中,Error表示错误,如果出现,通常需要升级硬件、调整JVM配置,或修改程序源代码来解决问题!Exception表示异常,即程序有可能无法执行到预期正确的结果,在异常中,主要分为一般异常和RuntimeException,如果程序执行过程中,出现一般异常,编写时代码时,调用方法的代码会出错,需要通过try…catch或throws方式进行处理,如果出现RuntimeException,则没有明确的语法要求,在源代码中并不会提示任何错误!无论是错误,还是异常,都是在运行过程中才暴露出来的!

Java语言对RuntimeException及其子孙类异常没有作语法的约束,即使某个方法可能抛出这些异常,但是,并不需要在程序代码中显式的进行语法的处理,即没有try…catch或throws源代码也不会报错!主要因为这些异常出现的频率可能很高,并且,这些异常是可以杜绝的!

一般的异常,是一定有出现的概率的,万一出现了,就必须要有对应的解决方案,所以,这些异常,在Java的语法中要求必须try…catch或throws,以对这些异常进行处理!

对异常处理的本质主要是“善后;给出一定的警示,避免再次出现”!

在编写项目时,如果调用某个方法可能出现异常,如果当前代码适合处理(能善后,能警示),则应该捕获并处理(try…catch),如果不适合处理,则应该抛出(throw+throws)。

例如,在项目中,如果Service组件中出现了异常,但是,Service组件并不负责与客户端进行交互,则无法直接给予客户端错误提示(警示),应该将异常抛出(throws),如果Controller组件中出现了异常,由于控制器可以给予客户端错误提示,应该捕获并处理(try…catch),在处理过程中,响应错误提示到客户端;如果Service把异常捕获并处理了,则在Controller中将无法发现异常,更加无法处理异常,也就无法给客户端错误提示了,则异常就没有被正确的处理!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈泡腾片

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值