学习笔记1 :Java基础

1、JVM

(1)Java虚拟机:是运行所有Java程序的抽象计算机,是Java语言的运行环境。

(2)JVM包括:一套字节码指令集、一组寄存器、一个栈、一个垃圾回收堆和一个存储方法域

(3)跨平台:JVM在执行字节码时,把字节码解释成具体平台上的机器指令执行。一套代码,一次编译,多平台运行。但是,不同平台需要不同的虚拟机。

2、Java的编译

(1)Java源文件 → 编译 →  .class字节码文件

(2)JVM加载.class并运行

(3)Java在编译过程中,会把计算表达式计算出来,所以代码中计算表达式和数字常量的运行效率是一样的。

3、Java项目基本结构

(1)项目 → 包 → 类(源文件)

(2)一个源文件中,只能有一个public的类(同名),如果同时定义了其他类,不能用public修饰。

(3)包名层级结构:cn.xzhouse.erp.user ,可遵循一些命名规则,如:com.公司名.项目名.模块名.xxx , team.团队名.项目名.模块名.xxx

 4、变量默认值

(1)成员变量有默认值,局部变量没有(存储在JVM的栈中)

(2)局部变量需要给初始值

(3)引用类型成员变量,默认值null

(4)数组里的对象,默认null

5、向上造型与继承

(1)父类型的引用指向子类的对象。一个子类的对象可以向上造型为父类的类型。

(2)Aoo o1 = new Boo(); //父类型Aoo引用指向子类型Boo的对象,其实就是多态。

(3)单继承:extends

(4)可实现多个协议:implements

6、构造方法

(1)默认提供一个无参构造方法。如果自定义了构造方法,默认的无参构造方法则不再提供。

(2)为符合JavaBean(一种软件组件模型)的规则,建议任何情况下,都确保提供无参构造方法。

(3)子类构造方法调用之前,默认会先调父类无参构造方法(注意,此时可能父类没有无参构造方法,会报错);但是如果子类主动调用父类构造方法,则不会再默认调用父类无参构造方法。

(4)子类构造方法里调用父类构造方法,比如super(),必须放在第一行。

7、修饰符

(1)默认(不写)是本类和同包可用;
(2)protected:子类,本类,同包可用;
(3)final:不可变不可重写不可继承;
(4)public:最大限度,均可
(5)private:最小限度,私有
(5)static:静态
(6)static final :静态常量,在编译时替换为具体常量值,效率高 。如,static final String str = "常量字符串";
(7)abstract :修饰抽象方法、抽象类,同时,抽象方法必须放在抽象类里。

8、静态

(1)static:修饰的变量储存在方法区,是属于类的,且全局只一份
(2)赋值:使用静态块、静态方法给静态变量赋值
public class MyClass {
    public static int staticVar;
    // 在静态块中为静态变量赋值
    static {
        staticVar = 10;
    }
}

public class MyClass {
    public static int staticVar;
    // 在静态方法中为静态变量赋值
    public static void setStaticVar(int value) {
        staticVar = value;
    }
}
(3)访问:类名.属性名
 

9、内存管理

(1)堆:对象,包括对象的实例变量、字符串常量池。

(2)栈:局部变量,包括方法参数;

(3)方法区:.class字节码文件、静态变量、所有方法;

(4)多线程:每条线程都有自己的栈内存,但是堆只有一个。

(5)局部变量和方法参数:方法被调用时,会在栈中开辟“栈帧”,存储所有局部变量,包括参数。方法调用结束,栈帧释放。

(6)字符串常量池:在堆中,存在字符串常量池,缓存字面量的字符串,并且只存一份。缓存的内容,就是堆空间中字符串对象的地址。另外:字面量运算后得到的字符串,也当做字面量字符串进行存储。

10、内部类

(1)成员内部类和匿名内部类。
(2)内部类可以使用外部类的变量,包括私有变量。
(3)内部类访问外部类变量:外部类.this.变量访问。
(4)匿名内部类:使用匿名内部类创建一个派生类对象,并且对象只被创建一次,简洁方便。
My subObject = new My(){
      @Override
      public void test() {
           System.out.println("test"+"new");
      }
};

(5)内部类有独立的.class文件,包括匿名内部类。

(6)匿名内部类中,不能修改外面变量的值,因为那个外部变量被默认final。而且,外部变量如果改变了值,内部也无法使用,因为不符合final规则。

(7)成员内部类实例化对象的语法: 外部类对象.new 内部类()。例如,Inner inner = Outer.new Inner();

11、方法

(1)方法重载:支持
  • 可重载:相同方法名,不同的参数个数、类型、参数顺序。
  • 不可重载:不能通过方法的访问权限、返回值类型、抛出的异常类型来进行重载。
  • 继承的重载:如果基类方法为private,不能在派生类中对其重载(需要可继承的权限)。一般来说,我们在谈论重载的时候,都是局限在一个类里面。
(2)方法重写:支持
  • 权限:子类中的覆盖方法的权限修饰符不能比父类权限小,如父类的方法是public,子类不能定义为默认、private、protected。
  • 异常:子类中的覆盖方法所抛出的异常必须和父类中所抛出的异常一致或是其子类。
  • 不可重写:父类的方法为static、private、final,不可重写。
  • 抽象类:抽象类的子类,必须实现抽象方法的重写。
(3)传值:调用方法时传递参数,都是“值传递”。
(4)特殊方法:
  • toString():重写该方法,可以实现自定义的控制台输出。

12、接口

(1)定义接口:interface 关键字
(2)接口里只能是常量、抽象方法,访问权限都是公开的。JDK8之后,也会有default方法。
(3)接口里的常量,默认为public+static+final;方法默认为public+abstract。
(4)接口也会有字节码文件。
(5)实现接口,需要重写接口里的方法,且只能是public。
(6)一个类可以实现多个接口。
(7)接口可以继承接口。
(8)一个类,同时存在继承实现接口,则先声明继承(extends),后声明实现(implements)。

13、运算符和连接符

(1)算术运算符、逻辑运算符、位运算符、关系运算符、自增自减运算符、赋值运算符、条件运算符和其他语言类似。

(2)连接符:+号作为字符串连接符时,遇到“”,其后的所有内容都会自然拼接,不会做加法运算了。遇到“”前的+号该怎么计算就怎么计算。

(3)instanceof运算符:必须是引用类型,不能是基本类型

  • 判断 obj是否为某个class的实例对象
  • 判断 obj是否为某个接口的实现类的实例对象
  • 判断 obj 为 class 类的直接或间接子类的实例对象

14、计时器

(1)java.util.Timer:计时器类
(2)java.util.TimerTask:任务,是实现Runnable接口的抽象类。
(3)常用启动方法:schedule(TimerTask task, long delay, long period)
     Timer timer = new Timer();
        timer.schedule(new TimerTask() {
        @Override
        public void run() {
            //计时器执行的事件
        }
    }, 10, 10);   
(4)停止:cancel()
 

15、随机数

(1)Math.random() :获取0-1之间的一个double,不包括1。
(2)java.util.Random:只要种子一样,产生的随机数也一样,默认使用当前系统时钟作为种子。
        Random random = new Random();
        int num = random.nextInt(2);
        /**
        nextBoolean() - 返回均匀分布的 true 或者 false
        nextBytes(byte[] bytes)
        nextDouble() - 返回 0.0 到 1.0 之间的均匀分布的 double
        nextFloat() - 返回 0.0 到 1.0 之间的均匀分布的 float
        nextGaussian()- 返回 0.0 到 1.0 之间的高斯分布(即正态分布)的 double
        nextInt() - 返回均匀分布的 int
        nextInt(int n) - 返回 0 到 n 之间的均匀分布的 int (包括 0,不包括 n)
        nextLong() - 返回均匀分布的 long
        setSeed(long seed) - 设置种子
         */   

(3)java.util.concurrent.ThreadLocalRandom:每一个线程有一个独立的随机数生成器,用于并发产生随机数,能够解决多个线程发生的竞争争夺。效率更高!

public class My {
    public static void main(String[] args) {
        new MyThread().start();
        new MyThread().start();
    }
}
class MyThread extends Thread{
    @Override
    public void run() {
        for (int i =0;i<2;i++){
            System.out.println(Thread.currentThread().getName() + ": "+ ThreadLocalRandom.current().nextInt(10));
        }
    }
}

(4)java.Security.SecureRandom:提供加密的强随机数生成器 (RNG),要求种子必须是不可预知的,产生非确定性输出。

  

16、字符集和字符编码

(1)字符集:ASCII、Unicode
(2)Unicode 编码方案:UTF-8、UTF-16、UTF-32
(3)UTF-8
  • 根据字符所占字节不同,UTF-8有1字节、两字节、三字节、四字节编码。英语字母,UTF-8 编码和 ASCII 码是相同的,都是1字节。

   

  • Unicode中文是两个字节,所以UTF-8传输一个中文,需要三个字节。

17、Url的编码(百分号编码)

(1)为什么需要Url编码:因为有些字符会引起歧义

  • Url参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?q=abc& ie=utf-8。
  • Url的编码格式采用的是ASCII码,而不是Unicode,不能在Url中包含任何非ASCII字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。
 

(2)哪些字符需要编码

  RFC3986文档规定,Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。

  •  保留字符

  Url可以划分成若干个组件,协议、主机、路径等。有一些字符(:/?#[]@)是用作分隔不同组件的,还有一些字符(!$&'()*+,;=)用于在每个组件中起到分隔作用的。当组件中的普通数据包含这些特殊字符时,需要对其进行编码。

     

  • 不安全字符:可能会引起解析程序的歧义,这些字符被视为不安全字符。

     

   对于Url而言,只有普通英文字符和数字,特殊字符-_.~还有保留字符,才能出现在未经编码的Url之中。其他字符均需要经过编码之后才能出现在Url中。

(3)如何对Url中的非法字符进行编码

  Url编码通常也被称为百分号编码,使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的十六进制形式。Url编码默认使用的字符集是US-ASCII。例如a在US-ASCII码中对应的字节是0x61,那么Url编码之后得到的就是%61,在地址栏上输入http://g.cn/search?q=%61%62%63,实际上就等同于在google上搜索abc了。又如@符号 在ASCII字符集中对应的字节为0x40,经过Url编码之后得到的是%40。

     

  对于非ASCII字符,需要使用ASCII字符集的超集进行编码得到相应的字节,然后对每个字节执行百分号编码。比如中文。

  对于Unicode字符,RFC文档建议使用utf-8对其进行编码得到相应的字节,然后对每个字节执行百分号编码。如“中文”使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87,经过Url编码之后得到“%E4%B8%AD%E6%96%87”。如果使用的是GB2312,那么得到的编码又会不同。

18、架构

(1)高内聚低耦合

(2)侵入性:当调用一个功能时,其要求我们为其修改其他额外的代码,这就是侵入性,它不利于程序后期的维护与扩展,应当尽量避免。

19、原码、反码、补码

(1)原码:符号位+数字的二进制 ,如  -1 = 1000 0001(原)
(2)反码:正数反码=原码, 负数反码= 原码符号位不变其余各位取反,如 -1 = 1111 1110(反)
(3)补码:正数的补码=原码,对于负数,符号位不变,反码+1=补码,如 -1 = 1111 1111(补)。计算机利用补码,实现减法、乘除法转为加法的运算。
  • 例如:  

        [-128] 原码 = 1000  0000 \x09发生了溢出

      [-128] 反码 = 1111    1111 \x09除符号位外,各位取反

      [-128] 补码 = 1000  0000 \x09反码的末位加1,不能影响符号位

  • 规定0的补码是0000 0000补 ,1000 0000补表示8位字长的最低数 -128。所以8位字长可以表示的范围为:[-128,127] 
(4)以上为假设计算机字长为1字节(int 占4字节),如果从低字长转为高字长,补码左侧补符号位到满足高字长的位数。

  例如:

  • 8位字长 (2) 转为16位字长的(2)

  8位字长补码 0000 0010补  ——>  16位字长补码 0000 0000 0000 0010补

  • 8位字长 (-2) 转为16位字长的(-2)

  8位字长补码 1111 1110补 ——> 16位字长补码 1111 1111 1111 1110补 

 

   附录:

1、API 文档:JavaTM Platform Standard Edition 6 API 规范

2、JAVA资源下载:http://doc.vrd.net.cn/ 

posted @ 2023-11-29 17:26  执着的怪味豆  阅读(7)  评论(0编辑  收藏  举报