1.Java入门知识点

java入门知识点查漏补缺

1.特点

​ 跨平台/可移植性,安全性,面向对象,高性能,分布式,多线程,健壮性

2.java程序运行过程

image-20210913150027635

JDK:开发>JRE:运行(游戏)>JVM:规范

3.配置环境变量

JAVA_HOME:jdk安装路径

Path:%JAVA_HOME%\bin;

classpath:jdk1.5以上不用配置

检验:cmd->java -version

编译:javac HelloWorld.java

运行:java HelloWorld

注:一个源文件至多只能声明一个public的类,其他类的个数不限

4.注释

//单行注释
/*多行注释
    123
    123
*/
/**
	文档注释,后期生成项目api文档
*/

5.标识符

  1. 字母,下划线_,美元符号$开头
  2. 其他部分可以是字母,下划线_,美元符$和数字的任意组合
  3. 大小写敏感,长度无限制
  4. 不可以是关键字

命名规范:

  • 类名:首字母大写
  • 方法或变量名:第一个小写,从第二个单词开始首字母大写(驼峰原则)
  • 采用Unicode国际字符集,支持汉字(不推荐)

6.变量

类型声明位置从属于生命周期
局部变量方法或语句块中方法/语句块从声明位置开始直到方法结束
成员变量(实例变量)类内部,方法外部对象对象创建,成员变量也随之创建
静态变量(类变量)类内部,static修饰类被加载,静态变量有效
//局部变量
public void test(){
    int i;
    int j=i+5;//编译出错,i未被初始化
}
//成员变量
public class Test{
    int i;//如果不自行初始化,它会自动初始化成该类型的默认值
}
//静态变量,如果不自行初始化,与成员变量相同会自动初始化成该类型的默认初始值。

​ 实例变量的默认初始值

int0
double0.0
char‘\u0000’
booleanfalse

7.常量

final type var = value;

不能再做修改的量。

命名规则:大写字母和下划线,例如:MAX_VALUE

8.数据类型

  • 基本数据类型(三类八种)

    • 数值型 byte,short,int,long,double,float

    • 字符型 char

    • 布尔型 boolean

      byte1字节-128~127
      short2字节-32768~32767
      int4字节大约21亿
      long8字节264
  • 引用数据类型:统一为4个字节

    • 类 class
    • 接口 interface
    • 数组
  • java整形默认为int型,声明为long型后加"l"或"L"(不是必须)

  • 浮点型 Floating Point Number

    • float 单精度 7位有效数字 有一个后缀f或F9(必须加)
    • double 双精度 15位有效数字 默认
    float f = 3.14F;
    double f1 = 3.14;
    double f2 = 3.14D;
    //错误:
    float f3 = 3.14;//从double转为float可能会有精度损失,不能直接赋值给float
    //3.14是double型的浮点常量,不能直接赋值给float
    
    • 浮点型不适合在容许0误差的金融计算领域,如果需要进行不产生误差的精确计算需要用BigDecimal类
    • 浮点型数据比较一:
    float f = 0.1f;
    double d = 1.0/10;
    System.out.println(f==d) //结果为:false
      // == 在基本数据类型中用于比较数值;在引用数据类型中比较地址值
    
    • 浮点型数据比较二:
    float f = 4231315534213L;
    float f1 = d1+1;
    System.out.println(f == f1); //结果为:true
    
    • 浮点数是不精确的,尽量不要直接比较,可能会有问题。
    • 字长有限,浮点数能够精确表示的数是有限的,因而也是离散的,浮点数一般存在误差,很多数字无法精确的表示,结果只是接近,不是等于。
    • java.math包下两个有用的类:BigInteger和BigDecimal类,可以处理任意长度的数值。BigInteger实现了任意精度的整数运算。BIgDecimal实现了任意精度的浮点运算。
    • 雷区!:
      • 不要使用浮点数进行比较!!!
      • 需要比较时使用BigDecimal类
  • 字符型 char

    • Unicode编码,65536个字符
    • 'A’是一个字符,"A"是含有一个字符的字符串
    • 占用2个字节
    转义字符含义unicode编码
    \b退格\u0008
    \n换行\u000a
    \r回车\u000d
    \t制表符(tab)\u0009
    \"双引号\u0022
    \’单引号\u0027
    \\反斜杠\u005c
    • String类其实就是字符序列
  • 布尔型 boolean

    • 两个常量值:true和false
    • 内存中占1个字节或4个字节
    • 注意:不可以使用0或非0的整数替代true和false,这点和C语言不同。
    • if(flag==true)不推荐使用
    • 建议:if(flag)或if(!flag)
    • 关于boolean类型几个字节的说明:
      • 在《java虚拟机规范》书中描述:虽定义了boolean这种数据类型,但又对它提供有限支持,在java虚拟机中没有任何供boolean值专用的字节码指令。java语言表达式所操作的boolean值在编译后都使用java虚拟机中的int数据类型来代替,而boolean数组将会被编译成java虚拟机中的byte数组,每个boolean元素占8位,也就是说,JVM规范指出boolean当做int处理也就是4个字节,boolean数组当做byte数组处理,占1个字节。
      • 得出boolean类型单独使用是4个字节,在数组中则是1个字节。

9.运算符 (operator)

  • 算术运算符

    • 整数运算:两操作数一个为long,结果为long;没有long时,结果为int,即使操作数为short,byte,结果也是int
    • 浮点运算:两操作数一个为double,结果为double;只有两个操作数都是float,则结果才是float
    • 取模运算:操作数可以为浮点数,一般使用整数,结果是“余数”;“余数”符号和左边操作数相同,如:7%3=1,-7%3=-1,7%-3=1
  • 赋值运算:

    • a*=b+3; //等价于:a = a*(b+3)
  • 逻辑运算:结果都是boolean值

    逻辑运算符号含义
    逻辑与&(与)两个操作数为true,结果为true,否则为false
    逻辑或|(或)有一个为true,结果为true
    短路与&&只要有一个为false,直接返回false
    短路或||只要有一个true,则返回true
    逻辑非!取反:!false为true,!true为false
    逻辑异或^相同为false,不同为true
  • 位运算:二进制的运算

    符号含义
    ~取反
    &按位与
    |按位或
    ^按位异或
    <<左移,左移一位相当于乘以2
    >>右移,右移一位相当于除以2
    • 3*2怎样算最快?
      • 左移一位 3<<1
  • 优先级的问题

    • 算术 > 关系(> >= < <= == !=)> 逻辑(&>^>|)> && > ||
    • 注意:逻辑与,逻辑或,逻辑异或的优先级
      • 逻辑非>逻辑与>逻辑或
    // a||b&&c的运算结果为:a||(b&&c),而不是(a||b)&&c
    

10.自动类型转换

  • 容量小的数据类型可以自动转换为容量大的数据类型

image-20210923172922905

  • 可以将整型直接赋值给byte,short,char等类型变量,而不需要进行强制类型转换,只要不超出范围即可。

    short b = 12;//合法
    short b1 = 1234567;//非法,超出范围
    

11.强制类型转换(cast)

  • 强制类型转换,又被称为造型(cast),用于强制的转换一个数值的类型。在有可能丢失信息的情况下进行的转换是通过造型来完成的,但可能造成精度降低或溢出。

  • 当将一种类型强制转换成另一种类型,而又超出了目标类型的表数范围,就会被截断成为一个完全不同的值。

    int x = 300;
    byte bx = (byte)x; //值为 44
    
  • 不能在布尔类型和任何数值类型之间做强制类型转换

12.随机数

  • Math.random()用于产生0到1区间的double型的随机数,但不包括1

    int i = (int)(Math.random()*6);//产生[0,5]之间的随机数
    

13.控制语句

  • switch语句:根据表达式的值从相匹配的case开始执行,一直执行到break或switch末尾,如果不匹配,则进入default语句
  • switch语句的case标签:在jdk1.5之前必须是整数(long类型除外)或枚举,不能是字符串,在jdk1.7之后允许使用字符串(String)

14.方法的重载(overload)

  • 方法名相同,参数不同的方法
  • 不同的含义:形参类型,形参个数,形参顺序不同
  • 只有返回值不同不构成方法的重载
    • 如:int fun(String str)与void fun(String str)不构成方法重载
  • 只有形参的名称不同,不构成方法的重载
    • 如:int a(String str){}与 int a(String s){}不构成方法重载

15.面向对象与面向过程的理解

  • 表结构对应:类结构
  • 一行数据对应:一个对象
  • 表中所有数据对应:这个类的所有对象
  • 面向过程:执行者思维,解决简单问题(如何开车?)
  • 面向对象:设计者思维,解决复杂、需要协调的问题(车由什么组成?)
  • 两者相辅相成,宏观上:通过面向对象整体设计;微观上:执行和处理数据仍是面向过程

16.构造方法(构造器 constructor)

this.id(表示属性id) = id(表示形参id);
  • java通过new关键字来调用构造器,从而返回该类的实例
  • 构造器有返回值!但不能定义返回值类型(返回值类型肯定是本类)不能使用return
  • 如果没有定义,则编译器会自动定义一个无参的构造器,如果已定义,则不会自动添加!
  • 构造器方法名必须和类名一致!!
  • 对象的创建完全是由构造方法实现的吗?
    • 不完全是。构造方法是创建 Java 对象的重要途径,通过 new 关键字调用构造器时,构造器也确实返回了该类对象,但这个对象并不是完全由构造器负责创建的。创建一个对象分为如下四 步:
      1. 分配对象空间,并将对象成员变量初始化为 0 或空
      2. 执行属性值的显式初始化
      3. 执行构造方法
      4. 返回对象的地址给相关的变量

17.JVM内存模型

image-20210923201828041

  • 从属于线程的内存区域(栈、计数器)

    ​ JVM 的内存划分中,有部分区域是线程私有的,有部分是属于整个 JVM 进程;我们将这部分归为一类。

      	1. 程序计数器(Program Counter Register),在 JVM 规范中,每个线程都有自己的
      程序计数器。这是一块比较小的内存空间,存储当前线程正在执行的 Java 方法的 JVM 指令址,即字节码的行号。如果正在执行 Native 方法,则这个计数器为空。
      	2. Java 虚拟机栈(Java Virtal Machine Stack),同样也是属于线程私有区域,每个线程在创建的时候都会创建一个虚拟机栈,生命周期与线程一致,线程退出时,线程的虚拟机栈也回收。虚拟机栈内部保持一个个的栈帧,每次方法调用都会进行压栈,JVM 对栈帧的操作只有出栈和压栈两种,方法调用结束时会进行出栈操作。该区域存储着局变量表,编译时期可知的各种基本类型数据、对象引用、方法出口等信息。
      	3. 本地方法栈(Native Method Stack)与虚拟机栈类似,本地方法栈是在调用本地方法时使用的栈,每个线程都有一个本地方法栈。
    
  • 堆(heap)

    ​ 堆(Heap),几乎所有创建的 Java 对象实例,都是被直接分配到堆上的。堆被所有的线程所共享,在堆上的区域,会被垃圾回收器做进一步划分,例如新生代、老年代的划分。Java 虚拟机在启动的时候,可以使用“Xmx”之类的参数指定堆区域的大小。

  • 方法区(Method Area)

    ​ 方法区与堆一样,也是所有的线程所共享,存储被虚拟机加载的元(Meta)数据,包括类信息、常量、静态变量、即时编译器编译后的代码等数据。
    方法区是一种 java 虚拟机的规范。由于方法区存储的数据和堆中存储的数据一致,实质上也是堆,因此,在不同的 JDK 版本中方法区的实现方式不一样。

    ​ JDK7 以前,方法区就是堆中的“永久代”。
    ​ JDK7 开始去“永久代”,把静态变量、字符串常量池都挪到了堆内存中。

    ​ JDK8 以后,“永久代”不存在了。存储的类信息、编译后的代码数据等已经移动到了MetaSpace(元空间)中,元空间并没有处于堆内存上,而是(直接内存)直接占用的本地内存(NativeMemory)。

  • 运行时常量池(Run-Time Constant Pool)(方法区中)

    ​ 这是方法区的一部分。常量池主要存放两大类常量:

    1. 字面量(Literal),如文本字符串、final 常量值。
    2. 符号引用,存放了与编译相关的一些常量,因为 Java 不像 C++那样有连接的过程,因此字段方法这些符号引用在运行期就需要进行转换,以便得到真正的内存入口地址。
  • 直接内存(Direct Memory)

    ​ 直接内存并不属于 Java 规范规定的属于 Java 虚拟机运行时数据区的一部分。Java 的NIO 可以使用 Native 方法直接在 java 堆外分配内存,使用 DirectByteBuffer 对象作为这个堆外内存的引用。

18.程序执行的内存分析过程

Java 虚拟机的内存可以简单的分为三个区域:虚拟机栈 stack、堆 heap、方法区method area。

  • 虚拟机栈(简称:栈)的特点如下:
    1. 栈描述的是方法执行的内存模型。每个方法被调用都会创建一个栈帧(存储局部变量、操作数、方法出口等)
    2. JVM 为每个线程创建一个栈,用于存放该线程执行方法的信息(实际参数、局部变量等)
    3. 栈属于线程私有,不能实现线程间的共享!
    4. 栈的存储特性是“先进后出,后进先出”
    5. 栈是由系统自动分配,速度快!栈是一个连续的内存空间!
  • 堆的特点如下:
    1. 堆用于存储创建好的对象和数组(数组也是对象)
    2. JVM 只有一个堆,被所有线程共享
    3. 堆是一个不连续的内存空间,分配灵活,速度慢!
  • 方法区(又叫静态区,也是堆)特点如下:
    1. 方法区是 JAVA 虚拟机规范,可以有不同的实现。
    2. JDK7 以前是“永久代”
    3. JDK7 部分去除“永久代”,静态变量、字符串常量池都挪到了堆内存中
    4. JDK8 是“元数据空间”和堆结合起来。
    5. JVM 只有一个方法区,被所有线程共享!
    6. 方法区实际也是堆,只是用于存储类、常量相关的信息!
    7. 用来存放程序中永远是不变或唯一的内容。(类信息【Class 对象,反射机制中会
      重点讲授】、静态变量、字符串常量等)

19.垃圾回收机制

  • 内存管理

    Java 的内存管理很大程度指的就是:堆中对象的管理,其中包括对象空间的分配和释
    放。
    对象空间的分配:使用 new 关键字创建对象即可
    对象空间的释放:将对象赋值 null 即可。垃圾回收器将负责回收所有”不可达”对象
    的内存空间。

  • 垃圾回收过程

    1. 发现无用的对象
    2. 回收无用对象占用的内存空间。
  • 垃圾回收相关算法

    • 引用计数法
    • 根搜索法(引用可达法)
  • JVM将堆内存划分为:Eden,Survior,Tenured空间

    image-20210923203436109

  • 三种垃圾回收器:Minor GC:用于清理年轻代区域;Major GC:用于清理年老代区域;Full GC:用于清理年轻代、年老代区域,成本较高,会对系统性能产生影响。

  • 在对 JVM 调优的过程中,很大一部分工作就是对于 Full GC 的调节。有如下原因可能
    导致 Full GC:

    1. 年老代(Tenured)被写满
    2. 持久代(Perm)被写满
    3. System.gc()被显式调用(System.gc是通知JVM,并不是运行)
    4. 上一次 GC 之后 Heap 的各域分配策略动态变化
  • 开发中容易造成内存泄露的操作:

    1. 创建大量无用对象
    2. 静态集合类的使用
    3. 各种连接对象(IO 流对象、数据库连接对象、网络连接对象)未关闭
    4. 监听器的使用不当
  • 其他要点:

    • 程序员无权调用垃圾回收器。
    • 程序员可以调用 System.gc(),该方法只是通知 JVM,并不是运行垃圾回收器。尽量少用,会申请启动 Full GC,成本高,影响系统性能。
    • finalize 方法,是 Java 提供给程序员用来释放对象或资源的方法,但是尽量少用

20. this、static、super关键字

  • this:创建好的对象的地址

    • 用于程序中产生二义性之处;普通方法中,this总是指向调用该方法的对象;构造方法中,this总是指向正要初始化的对象
    • 调用重载的构造器,必须位于构造方法的第一句。
    • this不能用于static方法中。
  • static关键字:

    • 该类的公用变量,属于类,类被载入时显式初始化
    • static成员变量只有一份,被该类的所有对象共享
    • 一般用”类名,类属性/方法“来调用
    • 在 static 方法中不可直接访问非 static 的成员。
  • 静态初始化块

    • 构造方法用于对象的初始化!静态初始化块,用于类的初始化操作!
    • 在静态初始化块中 不能直接访问非 static 成员。
  • super关键字

    • 直接父类对象的引用
    • 可以通过 super 来访问父类中被子类覆盖的方法或属性

21.包机制

  • com.java和com.java.haha这两个包没有包含关系,是两个完全独立的包,只是逻辑上看起来后者是前者的一部分。
  • java会默认导入java.lang包下的所有类,因此这些类可以直接使用
  • import java.util.*; 导入该包下的所有类,会降低编译速度,但不会降低运行速度。
  • 如果导入两个同名的类,只能用包名+类名来显示调用相关类:
    java.util.Date date = new java.util.Date();

22.继承和组合

  • java类没有多继承、接口有多继承
  • 子类继承父类,可以得到父类的全部属性和方法(除父类的构造方法),但不见得可以直接访问(比如父类私有的属性和方法)
  • 默认父类是java.lang.object
  • instanceof 是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对
    象时,返回 true;否则,返回 false。
  • final 关键字的作用:
    • 修饰变量: 被他修饰的变量不可改变。一旦赋了初值,就不能被重新赋值。
      • final int MAX_SPEED = 120;
    • 修饰方法:该方法不可被子类重写。但是可以被重载!
      • final void study(){}
    • 修饰类: 修饰的类不能被继承。比如:Math、String 等。
      • final class A {}
  • 组合:将父类对象作为子类的属性:子类通过调用这个属性来获得父类的属性和方法
  • “is -a”关系建议使用继承
  • “has-a”关系建议使用组合。

23.封装

  • 高内聚、低耦合

  • 访问控制符

  • image-20210923210617963

  • private 表示私有,只有自己类能访问

  • default 表示没有修饰符修饰,只有同一个包的类能访问

  • protected 表示可以被同一个包的类以及其他包中的子类访问,不同包中的非子类无法访问

  • public 表示可以被该项目的所有包中的所有类访问——只有继承子类能用

  • 【注】关于protected的两个细节:

    1. 若父类和子类在同一个包中, 子类可访问父类的 protected 成员,也可访问父类对象的 protected 成员。
    2. 若子类和父类不在同一个包中,子类可访问父类的 protected 成员,不能访问父类对象的 protected 成员。

24.多态(polymorphism)

  • 同一个方法调用,由于对象不同可能会有不同的行为

  • 要点:

    • 多态是方法的多态,不是属性的多态(多态与属性无关)

    • 多态的存在有3个必要条件:继承,方法重写,父类引用指向子类对象

    • 父类引用指向子类对象后,用父类引用调用子类重写的方法

    • 编译看左边,运行看右边

    • public static void main(String[ ] args) {
          Animal a1 = new Cat(); // 向上可以自动转型
          //传的具体是哪一个类就调用哪一个类的方法。大大提高了程序的可扩展性。
          animalCry(a1);
          Animal a2 = new Dog();
          animalCry(a2);
          //a2 为编译类型,Dog 对象才是运行时类型。
          
          /*编写程序时,如果想调用运行时类型的方法,只能进行强制类型转换。
          * 否则通不过编译器的检查。*/
          Dog dog = (Dog)a2;//向下需要强制类型转换
          dog.seeDoor();
      }
      
    • 向下转型中使用instanceof关键字

      public class TestCasting3 {
          public static void main(String[ ] args){
              Object obj = new String("哈哈哈");
              if(obj instanceof String){
                  String str = (String)obj;
                  System.out.println(str.charAt(0));
              }else if(obj instanceof StringBuffer){ 
                 	StringBuffer str = (StringBuffer) obj;
              	System.out.println(str.charAt(0));
              }
          }
      }
      

25.抽象类

  1. 有抽象方法的类只能定义为抽象类
  2. 抽象类不能实例化,即不能用new来实例化抽象类
  3. 抽象类可以包含属性,方法,构造方法,但是构造方法不能用来New实例只能用来被子类调用
  4. 抽象类可以有抽象方法,也可以有普通方法
  5. 抽象类只能用来被继承
  6. 抽象方法必须被子类实现

26.接口

  • 比“抽象类”还“抽象”的“抽象类”
  • 访问修饰符只能是public或默认(类同样如此)
  • 接口名:和类名相同的命名机制
  • extends:接口可以多继承
  • 常量:接口中的属性只能是常量,总是public static final修饰
  • 方法:接口中的方法只能是public abstract,可省略
  • 要点:
    • 子类通过implements来实现接口中的规范
    • 接口不能创建实例,但是可用于声明引用变量类型
    • 一个类实现了接口,必须实现接口中的所有方法,并且这些方法只能是public的
    • JDK1.8之前接口中只能包含静态常量,抽象方法,不能有普通属性,构造方法,普通方法
    • JDK1.8之和接口中包含普通的静态方法,默认方法
      1. 默认方法:允许给接口添加一个非抽象的方法实现,只需用default即可,所有这个接口的实现类都会通过继承得到这个方法
      2. 静态方法从属于接口,可以通过接口名直接调用

27.内部类

java内部类有四种,分别是静态内部类、非静态成员内部类、局部内部类、匿名内部类。

  • 成员内部类(静态/非静态)

    • 静态:

    • public class Person {
      
          private String name ="小明";
      
      	//静态成员内部类
      	static class Man{
          	private String name;
          	private int age;
       
            	public void show(){
                  System.out.println("男士");
          	}
      	}
      }
      测试:
      //创建静态的Man内部类的实例(静态的成员内部类)
      Person.Man man = new Person.Man();
      man.show();
      
    • 非静态:

    • public class Person {
          private String name ="小明";
      
      	//非静态成员内部类
      	class Woman{
              private String name="杜鹃";
      
              public Woman(){
      
              }
      
              public void display(String name){
                  System.out.println(name);//方法的形参
                  System.out.println(this.name);//内部类的属性
                  System.out.println(Person.this.name);//外部类的属性
              }
         	}
      }
      
      测试:
      //创建非静态的Woman内部类的实例(非静态的成员内部类)
      Person p = new Person();
      Person.Woman woman = p.new Woman();
      woman.display("lucy");
      
  • 局部内部类

    • public class Person {
          private String name ="小明";
      
          //局部内部类使用
          public Comparable getComparable(){
              //创建一个实现了Comparable接口的类:
              //方式一:局部内部类
              class MyComparable implements Comparable{
                  @Override
                  public int compareTo(Object o) {
                      return 0;
                  }
              }
              return new MyComparable();
          }
      }
      
  • 匿名内部类

    • 适合只需使用一次的类,比如:键盘监听操作等,在安卓开发,awt,swing中常见

    • public class Person {
      	private String name ="小明";
      
      	public Comparable getComparable(){
          //方式二:匿名内部类的方式
              return new Comparable(){
                  @Override
                  public int compareTo(Object o) {
                      return 0;
                  }
              };
          }
      }
      
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

懿所思

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

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

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

打赏作者

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

抵扣说明:

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

余额充值