学习笔记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、修饰符
8、静态
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; } }
9、内存管理
(1)堆:对象,包括对象的实例变量、字符串常量池。
(2)栈:局部变量,包括方法参数;
(3)方法区:.class字节码文件、静态变量、所有方法;
(4)多线程:每条线程都有自己的栈内存,但是堆只有一个。
(5)局部变量和方法参数:方法被调用时,会在栈中开辟“栈帧”,存储所有局部变量,包括参数。方法调用结束,栈帧释放。
(6)字符串常量池:在堆中,存在字符串常量池,缓存字面量的字符串,并且只存一份。缓存的内容,就是堆空间中字符串对象的地址。另外:字面量运算后得到的字符串,也当做字面量字符串进行存储。
10、内部类
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、方法
- 可重载:相同方法名,不同的参数个数、类型、参数顺序。
- 不可重载:不能通过方法的访问权限、返回值类型、抛出的异常类型来进行重载。
- 继承的重载:如果基类方法为private,不能在派生类中对其重载(需要可继承的权限)。一般来说,我们在谈论重载的时候,都是局限在一个类里面。
- 权限:子类中的覆盖方法的权限修饰符不能比父类权限小,如父类的方法是public,子类不能定义为默认、private、protected。
- 异常:子类中的覆盖方法所抛出的异常必须和父类中所抛出的异常一致或是其子类。
- 不可重写:父类的方法为static、private、final,不可重写。
- 抽象类:抽象类的子类,必须实现抽象方法的重写。
- toString():重写该方法,可以实现自定义的控制台输出。
12、接口
13、运算符和连接符
(1)算术运算符、逻辑运算符、位运算符、关系运算符、自增自减运算符、赋值运算符、条件运算符和其他语言类似。
(2)连接符:+号作为字符串连接符时,遇到“”,其后的所有内容都会自然拼接,不会做加法运算了。遇到“”前的+号该怎么计算就怎么计算。
(3)instanceof运算符:必须是引用类型,不能是基本类型
- 判断 obj是否为某个class的实例对象
- 判断 obj是否为某个接口的实现类的实例对象
- 判断 obj 为 class 类的直接或间接子类的实例对象
14、计时器
Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { //计时器执行的事件 } }, 10, 10);
15、随机数
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、字符集和字符编码
- 根据字符所占字节不同,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中的非法字符进行编码
对于非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、原码、反码、补码
- 例如:
[-128] 原码 = 1000 0000 \x09发生了溢出
[-128] 反码 = 1111 1111 \x09除符号位外,各位取反
[-128] 补码 = 1000 0000 \x09反码的末位加1,不能影响符号位
- 规定0的补码是0000 0000补 ,1000 0000补表示8位字长的最低数: -128。所以8位字长可以表示的范围为:[-128,127]
例如:
- 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/