java重要基础知识汇总

版权声明:未经博主同意,谢绝转载!(请尊重原创,感谢) https://blog.csdn.net/topdeveloperr/article/details/81414318

Table of Contents

抽象类与接口的区别

问题:什么时候用接口什么时候用抽象类?

java为什么不支持多继承

单根继承的优点1:兼容性

单根继承的优点2: 便利性

单根继承的优点3: 垃圾回收

continue关键字和break关键字

continue关键字

break关键字

枚举实现机制

递归

1 定义:程序调用自身的编程技巧称为递归( recursion)

2 组成

3 条件

4 生活中递归的表现

5 递归算法一般用于解决三类问题

6 缺点

基本数据类型

Float和Double详解

四种权限控制关键字

Super关键字

this关键字

final关键字

1 修饰变量

2 修饰方法

3 修饰类

java重要运算符

算术运算符

关系运算符

位运算符

transient关键字

关于size()方法和length属性

关于类Collections,Arrays,Objects

关于资源池

内部类

SOA


本篇博客是我个人对一些常用到的比较零碎的知识的一个大概总结。

抽象类与接口的区别

1.类可以实现多个接口,但是只能继承一个类

2.抽象类可以写方法实现,接口也可以写方法实现,不过需要加上default修饰。

3.从面向对象的角度来讲,抽象类和接口的抽象层次是不一样的

问题:什么时候用接口什么时候用抽象类?

抽象类的关键好处在于 能够实现面向对象设计的一个最核心的原则OCP(Open-ClosedPrinciple)。因此当我有一部分内容是不想让子类修改的,但是子类又都通用,同时各个自乐又有自己的特点,那么就适合使用抽象类。

abstract class和interface在Java语言中都是用来进行抽象类。从面向对象的角度来讲。我们知道所有的对象都是通过类来描绘的,但是反过来却不是这样。并不是 所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

在面向对象领域,抽象类主要用来进行类型隐藏。 我们可以构造出一个固定的一组行为的抽象描 述,但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类,而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个 抽象体。由于模块依赖于一个固定的抽象体,因此它可以是不允许修改的;同时,通过从这个抽象体派生,也可扩展此模块的行为功能。熟悉OCP的读者一定知 道,为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle),抽象类是其中的关键所在。

符合开发封闭原则,我可以对抽象出来的类进行扩展,但是只要是这个抽象类的子类,那么他必然能够。

从语法层面上讲,java单继承多实现,接口可以多实现。

java为什么不支持多继承

典型的支持多继承的语言就是C++。在OOP的世界里,单根继承意味着所有的类都会有一个终极类,java里面这个类就是Object。单根继承既可以说是一门语言的特性,也可以说是一门语言的一个选择。从纯粹技术的角度来说,java也可以做到多继承,只是如果那样的话那么java就不会再是我们今天所认识的java。

单根继承的优点1:兼容性

单根继承带来的一个效果就是所有的对象归根到底都是相同的基本类型。这带来的好处就是任何java出现的新类库中,兼容性的问题会大大降低,这一点很好理解。但是在C++之中,总是会有一些不兼容的接口,这虽然带来了一定的灵活性,但是对于不兼容的接口,往往就是要通过多继承来解决。

单根继承的优点2: 便利性

因为单根继承,所有的对象都会具备某些一样的功能,比如所有的对象都会有hashcode方法,有euqals方法。因此拿到一个对象时,无论这个对象从哪里来,我们都知道可以对他执行某些基本操作。参数传递也得到了简化。

单根继承的优点3: 垃圾回收

单根继承会使得垃圾回收变得简单很多。因为所有对象都保证具有其类型信息,因此不会因为无法确定类型信息而带来不便。垃圾回收正是java相对于C++的重要改进之一。

continue关键字和break关键字

continue关键字

使用地方:continue关键字只能用于循环结构。
作用:跳过本次循环,重新开始下一趟循环。

例子:

public class HelloWorld {
    public static void main(String[] args) {
          
        //打印单数     
        for (int j = 0; j < 10; j++) {
            if(0==j%2)  
                continue; //如果是双数,后面的代码不执行,直接进行下一次循环
             
            System.out.println(j);
        }
    }
}

打印结果是:1 3 5 7 9。

break关键字

使用地方:用于switch结构和循环结构

作用:
1.如果用于switch结构,跳出当前的case语句
2.如果用于循环结构中,跳出当前循环结构。

例子:

public class HelloWorld {
    public static void main(String[] args) {
          
        //打印单数     
        for (int j = 0; j < 10; j++) {
            if(0==j%2)  
                break; //如果是双数,直接结束循环
             
            System.out.println(j);
        }
    }
}

打印结果是:什么都不打印

枚举实现机制

枚举类型在编译器处理之后,是由一个final的继承Enum类的类实现的。该类是一个实实在在的类,该类当中,编译器还帮助我们生成了每个枚举类型的实例对象分别对应枚举中定义的每个枚举类型本身。

递归

1 定义:程序调用自身的编程技巧称为递归( recursion)

特点:一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合

2 组成

  • 边界条件
  • 递归前进段
  • 递归返回段

当边界条件不满足时,递归前进;当边界条件满足时,递归返回。

3 条件

1. 子问题须与原始问题为同样的事,且更为简单;

2. 不能无限制地调用本身,须有个出口,化简为非递归状况处理

4 生活中递归的表现

1.德罗斯特效应是递归的一种视觉形式。图中女性手持的物体中有一幅她本人手持同一物体的小图片,进而小图片中还有更小的一幅她手持同一物体的图片,依此类推。

2.我们在两面相对的镜子之间放一根正在燃烧的蜡烛,我们会从其中一面镜子里看到一根蜡烛,蜡烛后面又有一面镜子,镜子里面又有一根蜡烛……这也是递归的表现

3.从小就听过的例子:从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山...

但是上述例子是和递归相似的场景,但是软件当中定义的递归是要有一个终止条件的,否则就是死循环了。

递归算法一般用于解决三类问题

(1)数据的定义是按递归定义的。(Fibonacci函数

(2)问题解法按递归算法实现。

这类问题虽则本身没有明显的递归结构,但用递归求解比迭代求解更简单,如Hanoi问题。

(3)数据的结构形式是按递归定义的。

如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归地描述

6 缺点

1.递归算法解题相对常用的算法如普通循环等,运行效率较低

2.在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。

基本数据类型

简单类型

boolean

byte

char

short

Int

long

float

double

void

二进制位数

1

8

16

16

32

64

32

64

--

封装器类

Boolean

Byte

Character

Short

Integer

Long

Float

Double

Void

byte:

  • byte 数据类型是8位、有符号的,以二进制补码表示的整数;
  • 最小值是 -128(-2^7);
  • 最大值是 127(2^7-1);
  • 默认值是 0;
  • byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
  • 例子:byte a = 100,byte b = -50。

short:

  • short 数据类型是 16 位、有符号的以二进制补码表示的整数
  • 最小值是 -32768(-2^15);
  • 最大值是 32767(2^15 - 1);
  • Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
  • 默认值是 0;
  • 例子:short s = 1000,short r = -20000。

int:

  • int 数据类型是32位、有符号的以二进制补码表示的整数;
  • 最小值是 -2,147,483,648(-2^31);
  • 最大值是 2,147,483,647(2^31 - 1);
  • 一般地整型变量默认为 int 类型;
  • 默认值是 0 ;
  • 例子:int a = 100000, int b = -200000。

long:

  • long 数据类型是 64 位、有符号的以二进制补码表示的整数;
  • 最小值是 -9,223,372,036,854,775,808(-2^63);
  • 最大值是 9,223,372,036,854,775,807(2^63 -1);
  • 这种类型主要使用在需要比较大整数的系统上;
  • 默认值是 0L;
  • 例子: long a = 100000L,Long b = -200000L。
    "L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。

float:

  • float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
  • float 在储存大型浮点数组的时候可节省内存空间;
  • 默认值是 0.0f;
  • 浮点数不能用来表示精确的值,如货币;
  • 例子:float f1 = 234.5f。

double:

  • double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
  • 浮点数的默认类型为double类型;
  • double类型同样不能表示精确的值,如货币;
  • 默认值是 0.0d;
  • 例子:double d1 = 123.4。

boolean:

  • boolean数据类型表示一位的信息;
  • 只有两个取值:true 和 false;
  • 这种类型只作为一种标志来记录 true/false 情况;
  • 默认值是 false;
  • 例子:boolean one = true。

char:

  • char类型是一个单一的 16 位 Unicode 字符;
  • 最小值是 \u0000(即为0);
  • 最大值是 \uffff(即为65,535);
  • char 数据类型可以储存任何字符;
  • 例子:char letter = 'A';。

Float和Double详解

关于这两个数据类型,看过很多资料和博客也没有搞明白,博客质量也参差不齐。Float和Double就是java对于单精度和双精度提供的两种支持。

Double

事实上所谓的一个Double类型的数就是一个双精度类型的数。

双精度类型数据:Double precision data。 双精度型(DOUBLE)数据是具有更高精度的一种数据型数据。

双精度型数据采用固定长充浮点格式存储,占用8个字节.在计算机中每个双精度型数据占用8个字节(64位)的存储空间,可表示的正数范围是:4.94065645841247*10^-324~1.79769313486232*10^308,可表示的负数范围是:-1.79769313486232*10^308~-4.94065645841247*10^-324。双精度型数据最多可以有15位有效数字

Float

与双精度对应的就是单精度,单精度。

单精度数是指计算机表达实数近似值的一种方式。它的范围在负数的时候是从 -3.402823E38 到 -1.401298E-45,而在正数的时候是从 1.401298E-45 到 3.402823E38 

内存只分配32位,双精度分配64位内存,所以说双精度的精确度更高,但占用的内存也大,像金钱什么的要高度精确的就用它。

我们也常常把单精度类型数据叫做浮点类型的数。

引用:

记住java一定要用double,就算数值不大也要用double。
了解java虚拟机的底层会知道,float放在内存中其实是当作double来处理的,它不会比double更节约内存资源,对应的double虚拟机会直接以double形式来进行处理,快速而且精度高,但是如果用float,不但不会节约内存资源,虚拟机为了校验float的精度,会花费更多的系统资源,例如cpu时钟,程序执行步骤等等。
相对于这点,整数类型,能用int就用int,不要用什么short类型,道理是一样,其实虚拟机中short,char,boolean,byte在内存中都是以int形式来处理的,为了校验精度,虚拟机还会付出格外的开销,这样其实得不偿失,不要自作聪明以为节约了内存,其实错了。当然long类型例外,虽然long类型也会增加资源的开销,但是毕竟能完成int完成不了的功能。
还有,其实这些资源的开销对于整个应用程序和现有硬件资源而言就是九牛一毛,微乎其微,没有必要过于在意。就用习惯的形式即可。不要自作聪明的用特别的数据类型,浮点就double,整形就int,长整型就long,其它的必要性都不大(byte的话,用来做数组还是很方便的,除此不推荐使用。

关于精度:https://blog.csdn.net/a327369238/article/details/52354811/

四种权限控制关键字

修饰词 本类 同一个包的类 继承类 其他类
private × × ×
无(默认) × ×
protected ×
public

Super关键字

1:主要存在于子类方法中,用于指向子类对象中父类对象。

2:访问父类的属性

3:访问父类的函数

4:访问父类的构造函数

this关键字

this关键字代表自身,如果new了一个对象之后,这这个this就是一个指向这个对象自己的一个引用,如下图:

用途:

 (1)this调用本类中的属性,也就是类中的成员变量

 (2)this调用本类中的其他方法;

(3)this调用本类中的其他构造方法,调用时要放在构造方法的首行。

都非常好理解,因为指向的是对象自身,能操作的自然都是成员变量以及类的方法。

final关键字

final是java的一个关键字,他可以用于修饰类,方法,变量

1 修饰变量

final顾名思义是最终的意思,他修饰变量意味着这个变量的值不能再更改,只是在修饰引用变量的时候,这个值是指的引用不变,但引用的对象的内容是可变的,在修饰基本变量如int, string时,这意味着这个基本类型的值不能改变

2 修饰方法

final修饰的一个方法代表这个方法可以被继承,但是不可以被子类重写。一般对一个方法加上final关键字作为修饰,代表这个方法你认为不需要再重写和修改。

final方法比非final方法快的原因是在于final方法是在程序编译的时候就静态绑定了,但是在如今的jvm中这个速度已经可以忽略不计了。

3 修饰类

final类不能被继承,功能通常是完整的。

与finally区别?finally 通常用在异常处理中

与finalize区别?finalize是在Object类中定义的方法,是在垃圾回收时虚拟机调用来终结对象的方法

java重要运算符

算术运算符

假设整数变量A的值为10,变量B的值为20:

操作符 描述 例子
+ 加法 - 相加运算符两侧的值 A + B 等于 30
- 减法 - 左操作数减去右操作数 A – B 等于 -10
* 乘法 - 相乘操作符两侧的值 A * B等于200
/ 除法 - 左操作数除以右操作数 B / A等于2
取余 - 左操作数除以右操作数的余数 B%A等于0
++ 自增: 操作数的值增加1 B++ 或 ++B 等于 21(区别详见下文)
-- 自减: 操作数的值减少1 B-- 或 --B 等于 19(区别详见下文)

关系运算符

实例整数变量A的值为10,变量B的值为20:

运算符 描述 例子
== 检查如果两个操作数的值是否相等,如果相等则条件为真。 (A == B)为假(非真)。
!= 检查如果两个操作数的值是否相等,如果值不相等则条件为真。 (A != B) 为真。
检查左操作数的值是否大于右操作数的值,如果是那么条件为真。 (A> B)非真。
检查左操作数的值是否小于右操作数的值,如果是那么条件为真。 (A <B)为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。 (A> = B)为假。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。 (A <= B)为真。

位运算符

Java定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型(byte)等类型。

位运算符作用在所有的位上,并且按位运算。假设a = 60,b = 13;它们的二进制格式表示将如下

A = 0011 1100
B = 0000 1101
-----------------
A&b = 0000 1100
A | B = 0011 1101
A ^ B = 0011 0001
~A= 1100 0011

整数变量A的值为60和变量B的值为13

操作符 描述 例子
如果相对应位都是1,则结果为1,否则为0 (A&B),得到12,即0000 1100
| 如果相对应位都是0,则结果为0,否则为1 (A | B)得到61,即 0011 1101
^ 如果相对应位值相同,则结果为0,否则为1 (A ^ B)得到49,即 0011 0001
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。 (〜A)得到-61,即1100 0011
<<  按位左移运算符。左操作数按位左移右操作数指定的位数。 A << 2得到240,即 1111 0000
>>  按位右移运算符。左操作数按位右移右操作数指定的位数。 A >> 2得到15即 1111
>>>  按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。 A>>>2得到15即0000 1111

着重说一下一下几个

(1)<<

A为60,60对应的二进制为 0011 1100或者11 1100

A<<2即60 << 2即 0011 1100左移2位 得:1111 0000 。 换算成十进制就是240。

在这里我们可以得出移位运算的思路就是:把一个数化成对应的二进制,然后在进行对应的移位操作,再将移位后的二进制换算成需要的其他进制即可。

(2)>>

0011 1100 右移两位得: 0000 1111 。换算成十进制就是15.

(3)~

~A 即 0011 1100取反,得 1100 0011.换算成十进制就是-61

transient关键字

我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。

      然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

      总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中

1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

关于size()方法和length属性

在编程时经常会用到的两个东西,老是记混,特地看了一下。

length是数组的一个属性,在获取值的时候是按属性的方法获取。

而size()是链表的一个方法,用于获取链表的长度

关于类Collections,Arrays,Objects

在jdk源代码中提供了很多有用的工具类,它们的命名也有一定的规律。

Collections类提供了很多给容器使用的实用方法。

Arrays类提供了很多给给数组容器有用的方法

Object类提供了一些给Object类方法中的实用方法

关于资源池

资源池不仅仅是在java当中存在的概念,在软件世界里也是广泛应用的一个东西。

我们非常常见的资源池有:

  1. 数据库连接池
  2. web容器中的线程池
  3. web容器中的request,response对象池

使用资源池的原因和好处大致是相似的。无外乎创建关闭维护每一个资源是比较耗费成本的。因此我们可以维护一定数量的资源,来寻求一个效率上的平衡。

  1. 资源池引入的目的:提高性能
  2. 资源池运作机制:由资源池管理器提供一定数目的目标资源,当有请求该资源时,资源池分配给一个,然后给该资源标识为忙,    标   示为忙的资源不能再被分配使用,
  3. 资源池常有的参数  初始资源的数目:资源池启动时,一次建立的资源数目,资源池最少要保证在这个数目上.  最大资源的数目:当请求的资源超出这个数目,就等待。

内部类

本质上是java的一种"语法糖"。

现在又如下代码:

public class A {
  

    static class B {
       
    }

   class C {
       
    }
}

它在编译之后会产生三个.class文件,分别是:A.class,A$B.class,A$C.class.

注意B类和C类一个声明成了static的类,另一个则没有。他们的区别在于,不用static修饰的类在编译生成class文件之后,会生成一个默认的构造方法,这个构造方法里面会持有外部类A类的引用。而这有可能带来内存泄露问题。

而static修饰的类则不会在构造方法里持有外部类的引用。

详细信息可以参考:https://blog.csdn.net/qq_22706515/article/details/51321718

SOA

SOA 即 service-oriented architecture,翻译成中文就是面向服务的架构。是一种服务器架构理念。

是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。

SOA具有以下五个特征:
1、可重用
一个服务创建后能用于多个应用和业务流程。
2、松耦合
服务请求者到服务提供者的绑定与服务之间应该是松耦合的。因此,服务请求者不需要知道服务提供者实现的技术细节,例如程序语言、底层平台等等。
3、明确定义的接口
服务交互必须是明确定义的。Web服务描述语言(Web Services Description Language,WSDL)是用于描述服务请求者所要求的绑定到服务提供者的细节。WSDL不包括服务实现的任何技术细节。服务请求者不知道也不关心服务究竟是由哪种程序设计语言编写的。
4、无状态的服务设计
服务应该是独立的、自包含的请求,在实现时它不需要获取从一个请求到另一个请求的信息或状态。服务不应该依赖于其他服务的上下文和状态。当产生依赖时,它们可以定义成通用业务流程、函数和 数据模型。
5、基于开放标准
当前SOA的实现形式是Web服务,基于的是公开的W3C及其他公认标准.采用第一代Web服务定义的SOAP、WSDL和UDDI以及第二代Web服务定义的WS-*来实现SOA。

猜你喜欢

转载自blog.csdn.net/topdeveloperr/article/details/81414318