Java 核心技术卷一 随笔


Java 易混,重难点汇总

1.基础篇

整型
在这里插入图片描述
浮点
在这里插入图片描述
final 一般用于指示常量,即变量只能被赋值一次。一旦被赋值,就不能更改了。(即没有set方法)命名规则一般使用全大写及下划线。
类常量(外部类字段) 在一个类的多个方法中使用,位于main方法的外部。一般用 static final。声明为public时,其他类(内部类)的方法也可以使用该变量。
尽量不要强制转换boolean类型,可以使用条件表达式(三元操作符)b?1:0
static 可以理解为一份拷贝 相当于在某段时期是不会变化。直到静态常量被重新赋值。

自增与自减运算符

前缀 ++n 后缀 n++ 前缀形式会先完成加1;而后缀形式会使用变量原来的值。
在这里插入图片描述

构建字符串

多个较短的字符串构建字符串可以用以下方法:

StringBuilder builder = new StringBuilder();
builder.append(ch);
builder.append(str);
String completedString = builder.toString();

注:substring(a,b)的长度为b-a。
注:continue语句越过了当前循环体的剩余部分(未循环的部分),立刻跳到循环首部。
注:String[] args 即为命令行参数
注:String 是一组char[],因此==用来比较char下标,是否放置在同一个位置上
注:break 终止循环 continue是跳过本次循环(第i次执行被跳过)

新建变量

新建变量时,应该进行初始化操作,系统在运行过程不会对变量进行初始化。有报错的风险。

日期

一般而言,创建一个Date() 对象,所显示的时间格式并不符合中国时间格式,可用LocalDate()对象,但是不常用。
注:HH是24小时制,hh是12小时制
区别就是:大写的H是二十四小时制的小时数(0-23),小写的h是十二小时制的小时数(am/pm 1-12)
Java里面MM表示月 mm表示分钟 HH表示 24小时制 hh表示12小时制
Oracle里面 mm表示月 mi表示分钟 hh24表示小时
mm与m等,它们的区别为是否有前导零:H,m,s表示非零开始,HH,mm,ss表示从零开始。
比如凌晨1点2分,HH:mm显示为01:02,H:m显示为1:2。

构造器

构造器与类同名。 在构造类的对象时,构造器将实例化对象。
注: 预定义类是不需要初始化数据 因为没有数据
使用对象,需要先构造对象,指定初始化状态。

访问器和修改器

访问对象字段和修改对象字段的方法

隐式参数与显式参数

隐式参数是调用方法的目标(该类的字段),param = this.paramthis指向的是隐式对象。
为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
显式参数 方法名接收的参数就是显式参数。

实参与形参

实际存在的值 type param = 12; 为实参,public void method(type param...) param 为形参
java只有按值调用,即值传递。方法参数接收的是调用者提供的数据。是因为java对于数据的操作,是对该数据的备份的操作。
int a = 10;int y = 0;y=a; a =y; int a = 10 还是10 是不会变的。

对象

对象的行为 对对象施加的操作
对象的状态 施加操作之后,对象的响应
对象标识 相同的行为与状态的对象
构造方法 可以先设计字段,再根据字段关系,给类添加相应的方法。
工厂方法——java 自带类型线程池等类,可以通过实例化一个工厂类,对工厂类赋值,达到创建对象的目的。

对象克隆

原变量和副本都是同一个对象的引用,任何一个变量改变都会影响另一个变量。
因此被拷贝的对象的字段必须是不可变的,避免出现共享不安全的现象。
浅拷贝 指只拷贝不可变字段,即拷贝的字段是基本类型。
深拷贝 可变字段或者不可克隆的字段

可变对象与不可变对象

区分方法:其他内部值是否能改变。
可变对象
创建一个对象:
StringBuilder sb = new StringBuilder("a");
sb.append(“b”); //此时对象sb已经变化了 即sb的指向发生变化,不再指向a,而是b。
不可变对象
String a = "aaaaa";
静态方法 即可以不用实例出一个对象,可直接调用。一般用className.staticMethod()方式调用。例如 main()

对象关系

依赖 一个类的方法操纵另一个类的对象 例:订单(Order)需要访问Account对象查看信用状态。
关联 一个对象包含一些对象 例:订单(Order)包含一些物品(Item)对象
继承 extend 继承方法

数据私有
数据初始化
不使用过多的基本类型
不是每个字段都需要get、set方法
不应该过多分解类
类名和方法名体现职责
优先使用不可变类

内部类

内部类(inner class)是定义在另一个类中的类
● 内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。理解成这样就行
● 内部类可以对同一个包中的其他类隐藏起来。
● 当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous)内部类比较便捷。
作用:一个方法可以引用调用这个方法的对象数据域。内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。
只有内部类可以是私有类,而常规类只可以具有包可见性,或公有可见性。
构造器语法
在这里插入图片描述
内部类中声明的所有静态域都必须是final。原因很简单。我们希望一个静态域只有一个实例,不过对于每个外部对象,会分别有一个单独的内部类实例。如果这个域不是final,它可能就不是唯一的。内部类不能有static方法。

局部内部类

局部类不能用public或private访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。
它们不仅能够访问包含它们的外部类,还可以访问局部变量。不过,那些局部变量必须事实上为final。这说明,它们一旦赋值就绝不会改变。

匿名内部类(实现事件监听器和其他回调)

假如只创建这个类的一个对象,就不必命名了。这种类被称为匿名内部类(anonymous inner class)。
双括号初始化写法 {{}}
对于匿名子类 通过反射判断equals方法会失败
在这里插入图片描述
在这里插入图片描述>在这里插入图片描述
由于构造器的名字必须与类名相同,而匿名类没有类名,所以,匿名类不能有构造器
在这里插入图片描述
在这里插入图片描述

静态内部类

使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象。为此,可以将内部类声明为static,以便取消产生的引用。
前面例子中所使用的内部类不同,在Pair对象中不需要引用任何其他的对象,为此,可以将这个内部类声明为static
在这里插入图片描述
静态内部类的对象除了没有对生成它的外围类对象的引用特权外,与其他所有内部类完全一样
在这里插入图片描述
在这里插入图片描述

继承

基于已存在的类构造一个新类。继承已存在的类,即继承已存在类的方法和字段(域)。
场景:经理(Manager)的待遇与普通雇员(Employee)的待遇存在差异,也存在着很多相同的地方,经理可以在领取薪水的同时,在完成了预期的业绩之后还能得到奖金。Manager可以继承Employee中的属性和方法,再增加新功能。
使用 关键字extends表示继承
超类、基类或父类;子类、派生类或孩子类;
每个类只能有且只有一个超类,可以实现多个接口。所以只能是 class Employee extends Person (一个)
这是接口概念引入的原因。java不支持多继承,但是可以实现接口。多继承会导致语言逻辑复杂化。

1将公共操作和字段放在父类
2不要使用protected字段
3子类继承父类,不要过多的继承,导致代码耦合度过高
4重载方法不要改变该方法的作用

继承实例

父类Employee
子类Manager

泛型(类的概念)

在这里插入图片描述
泛型类(类工厂)
在这里插入图片描述
泛型类可以有多个类型变量。
在这里插入图片描述
T限制为实现了Comparable接口(只含一个方法compareTo的标准接口)的类。可以通过对类型变量T设置限定(bound)实现这一点:
在这里插入图片描述

泛型方法

在这里插入图片描述

类型变量的限定

在这里插入图片描述
在这里插入图片描述
Comparable接口是一个泛型类型。
类可以多个接口超类型但是继承只能一个类。

类型擦除

不能用类型参数代替基本类型,即只有List<String>
原始类型用第一个限定的类型变量来替换,如果没有给定限定就用Object替换。例如,类Pair<T>中的类型变量没有显式的限定,因此,原始类型用Object替换T。

多态情境下的擦除
在这里插入图片描述
强制类型转换在这里插入图片描述
<T>是不能用instanceof 进行比较的,也不能实例化,即new T(…), new T[…]或T.class
在这里插入图片描述
通过反射调用Class.newInstance方法来构造泛型对象,泛型数组,泛型类也引用不了类型变量,泛型类不能用于try...catch语句,但是可以使用泛型变量。
在这里插入图片描述
在这里插入图片描述

泛型的继承规则

是接口继承,跟T无关;ArrayList<T>类实现List<T>接口
涉及到通配符,允许类型参数变化
在这里插入图片描述
表示任何泛型Pair类型,它的类型参数是Employee的子类,如Pair<Manager>,但不是Pair<String>
通配符的超类型限定 ? super Manager
在这里插入图片描述
在这里插入图片描述
无限定通配符 Pair<?> 不如直接用 Pair<T>来的安全
在这里插入图片描述
可以用任意Object对象调用原始Pair类的setObject方法。

泛型Class类

在这里插入图片描述
Employee.class是类型Class的一个对象。

重载方法

通过继承父类的方法名,在要用super,不然就会之前一样系统防止重名,使用this,将会陷入无限调用自己,以至于陷入死循环。并且作用域从private 改为public
super若没有特别说明,默认没有参数的构造器。必须在子类的第一条语句,即紧挨字段下方。
代码

	 public class Employee {
		 public double getSalary(){
			 .....
		 }
	 }

	 public class Manager extends Employee{
		 public double getSalary(){
			 double baseSalary = super.getSalary();
		 	 return baseSalary + bonus;
		 }
	 }

当e引用Employee对象时,e.getSalary( )调用的是Employee类中的getSalary方法;当e引用Manager对象时,e.getSalary( )调用的是Manager类中的getSalary方法。称之为多态

对象包装器与自动装箱

Integerint的包装器。为final值。
添加 :

ArrayList<Integer> list = new ArrayList <Integer> ; 
list.add(3) 自动装箱为 list.add(Integer.valueOf(3));

Integer对象是不可变的:包含在包装器中的内容不会改变。不能使用这些包装器类创建修改数值参数的方法。

参数数量可变的方法

public static void main(String[] args) 其中args 的参数数量可变
等同于 public static void main(String... args)

枚举类型

所有的枚举类型都是Enum类的子类,常用方法:toString、valueOf、values

反射(不可过多使用)
Class类

Object类中的getClass()方法将会返回一个Class类型的实例。eg:java.lang.String
最常用的Class方法是getName。这个方法将返回类的名字
调用静态方法forName获得类名对应的Class对象。只有在className是类名或接口名时才能够执行
一个Class对象实际上表示的是一个类型,而这个类型未必一定是一种类。例如,int不是类,但int.class是一个Class类型的对象。
newInstance(),可以用来动态地创建一个类的实例,newInstance(),可以用来动态地创建一个类的实例(所谓的实例化)
Array类中的静态方法newInstance,它能够构造新数组。在调用它时必须提供两个参数,一个是数组的元素类型,一个是数组的长度。

利用反射分析类的能力

java.lang.reflect包中有三个类Field、Method和Constructor分别用于描述类的域、方法和构造器。
getModifiers的方法,它将返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用状况。
java.lang.reflect包中的Modifier类的静态方法分析getModifiers返回的整型数值。例如,可以使用Modifier类中的isPublic、isPrivate或isFinal判断方法或构造器是否是public、private或final
Class类中的getFields、getMethods和getConstructors方法将分别返回类提供的public域、方法和构造器数组,其中包括超类的公有成员。Class类的getDeclareFields、getDeclareMethods和getDeclaredConstructors方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超类的成员。
反射机制的默认行为受限于Java的访问控制。然而,如果一个Java程序没有受到安全管理器的控制,就可以覆盖访问控制。为了达到这个目的,需要调用Field、Method或Constructor对象的setAccessible方法。例如,
在这里插入图片描述
调用f.set(obj, value)可以将obj对象的f域设置成新值。(因为通过反射拿到的字段值是对象,而没有数据类型。)
ObjectAnalyzer将记录已经被访问过的对象

高级篇
接口

接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。
在这里插入图片描述在这里插入图片描述
接口可以看做是没有字段的抽象类。但是接口不是类,不能使用new运算符实例化一个接口。
可以使用instanceof检查一个对象是否属于某个特定的接口。
接口也可以继承。但是不能包含字段或者静态方法,可以包含常量
命名以及参数类型尽量不要重复,防止冲突
如果方法名冲突,父类接口优先级比子类接口优先级高 —“类优先”

接口与回调(**)

回调(callback)是一种常见的程序设计模式。在这种模式中,可以指出某个特定事件发生时应该采取的动作。例如,可以指出在按下鼠标或选择某个菜单项时应该采取什么行动。然而,由于至此还没有介绍如何实现用户接口,所以只能讨论一些与上述操作类似,但比较简单的情况。

lambda表达式(函数式编程)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

函数式接口(延迟执行)

对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。这种接口称为函数式接口
在这里插入图片描述
表达式System.out::println是一个方法引用(method reference),它等价于lambda表达式x -> System.out.println(x)
object::instanceMethod
Class::staticMethod
Class::instanceMethod
superClass::instanceMethod
this::instanceMethod
int[]::new是一个构造器引用,它有一个参数:即数组的长度。这等价于lambda表达式x -> new int[x]
Java有一个限制,无法构造泛型类型T的数组。表达式new T[n]会产生错误,因为这会改为new Object[n]
在这里插入图片描述

变量作用域

lambda表达式的数据结构存储自由变量的值,为闭包。
()->{闭包} 闭包的值是不能被改变的。lambda表达式中捕获的变量必须实际上是最终变量(effectively final)。指这个变量初始化之后就不会再为它赋新值。
在lambda表达式中声明与一个局部变量同名的参数或局部变量是不合法的。
在这里插入图片描述
在一个lambda表达式中使用this关键字时,是指创建这个lambda表达式的方法的this参数
如果想要立即执行代码,完全可以直接执行,而无需把它包装在一个lambda表达式中。之所以希望以后再执行代码

代理(不确定接口实现场景)

有一个表示接口的Class对象(有可能只包含一个接口),它的确切类型在编译时无法知道。这确实有些难度。要想构造一个实现这些接口的类,就需要使用newInstance方法或反射找出这个类的构造器。但是,不能实例化一个接口,需要在程序处于运行状态时定义一个新类。
这里借用反射 获取接口的参数与方法名 根据二分法查找到目标接口。代理起到的作用就是在接口被调用的时候,即运行时,将接口与方法调用结合起来。
即代理类是在程序运行过程中创建的。
所有的代理类都扩展于Proxy类。一个代理类只有一个实例域——调用处理器,它定义在Proxy的超类中。
代理类一定是publicfinal
可以通过调用Proxy类中的isProxyClass方法检测一个特定的Class对象是否代表一个代理类。

异常处理

异常分类
在这里插入图片描述
一个方法必须声明所有可能抛出的受查异常,而非受查异常要么不可控制(Error),要么就应该避免发生(RuntimeException)。如果方法没有声明所有可能发生的受查异常,编译器就会发出一个错误消息。
由于父类中方法没有抛出任何异常,所以,子类也不能抛出任何受查异常
1)找到一个合适的异常类。
2)创建这个类的一个对象。
3)将对象抛出。

捕获异常

将可能抛出已检查异常的一个或多个方法调用代码放在try块中,然后在catch子句中提供处理器代码。
在这里插入图片描述
如果类名不存在,则将跳过try块中的剩余代码,程序直接进入catch子句
要想捕获一个异常,必须设置try/catch语句块
在这里插入图片描述
捕获那些知道如何处理的异常,而将那些不知道怎样处理的异常继续进行传递。
如果想传递一个异常,就必须在方法的首部添加一个throws说明符,以便告知调用者这个方法可能会抛出异常。
不允许在子类的throws说明符中出现超过超类方法所列出的异常类范围。

finally子句

不管是否有异常被捕获,finally子句中的代码都被执行
在这里插入图片描述
1)代码没有抛出异常。执行标注的1、2、5、6处。
2)抛出一个在catch子句中捕获的异常。在上面的示例中就是IOException异常。在这种情况下,程序将执行try语句块中的所有代码,直到发生异常为止。此时,将跳过try语句块中的剩余代码,转去执行与该异常匹配的catch子句中的代码,最后执行finally子句中的代码。如果catch子句没有抛出异常,程序将执行try语句块之后的第一条语句。在这里,执行标注1、3、4、5、6处的语句。如果catch子句抛出了一个异常,异常将被抛回这个方法的调用者。在这里,执行标注1、3、5处的语句。
3)代码抛出了一个异常,但这个异常不是由catch子句捕获的。在这种情况下,程序将执行try语句块中的所有语句,直到有异常被抛出为止。此时,将跳过try语句块中的剩余代码,然后执行finally子句中的语句,并将异常抛给这个方法的调用者。在这里,执行标注1、5处的语句。try语句可以只有finally子句,而没有catch子句
注:建议解耦合try/catch和try/finally语句块。
1.只在异常情况下使用异常机制,因为捕获异常非常耗时。
2.尽量不要写多个try语句,可以有多个catch捕获语句
3.选对合适的异常

分析堆栈轨迹元素
基本日志

用一个静态变量存储日志记录器的一个引用,防止被垃圾回收
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

集合(接口)

队列Queue<E>:“先进先出”原则,
如果需要一个循环数组队列,就可以使用ArrayDeque类,是有界集合循环数组要比链表更高效
如果需要一个链表队列,就直接使用LinkedList类,这个类实现了Queue接口。如果程序中要收集的对象数量没有上限,就最好使用链表来实现。
Collection接口(不允许有重复对象)
Iterator接口 next方法可以逐个访问集合中的每个元素。
在这里插入图片描述
List是有序集合

并发

一个程序同时执行多个任务。通常,每一个任务称为一个线程(thread),它是线程控制的简称。可以同时运行一个以上线程的程序称为多线程程序(multithreaded)。
调用Thread.sleep不会创建一个新线程,sleep是Thread类的静态方法,用于暂停当前线程的活动。

线程
  1. Runnable接口的run方法
    在这里插入图片描述
    2.由Runnable创建一个Thread对象
    在这里插入图片描述
锁对象

在这里插入图片描述
关键词 synchronized
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值