Java核心卷1笔记

本文详细介绍了Java的基础知识,包括程序设计结构(如类名规则、注释、数据类型及其存储、变量与常量、运算符、字符串操作、数组、对象与类的继承、泛型以及集合框架),为初学者提供了全面的Java入门指南。
摘要由CSDN通过智能技术生成

3. Java的基本程序设计结构

3.1 一个简单的Java应用程序

  • Java区分大小写
  • 类名:大写字母开头,每个单词首字母大写
  • 源代码文件与公共类名字相同
  • 编译得到类字节码文件
  • 函数调用:object.method(parameters)

3.2 注释

在Java中,有3种注释方式

//第一种
/* 
第二种
*/
/**
第三种
*/

3.3 数据类型

8种基本类型,4种整型,2种浮点类型,1种字符类型,1种布尔类型

3.3.1 整型

类型存储需求取值范围
int4字节-2^31 ~ 2^31-1
short2字节-2^15 ~ 2^15-1
long8字节-2^63 ~ 2^63-1
byte1字节-128 ~ 127

长整型数值有后缀L或l,十六进制数值有前缀0x或0X,八进制有前缀0,二进制有前缀0b或0B。

Java没有任何无符号形式的整型。

3.3.2 浮点类型

类型存储需求取值范围
float4字节
double8字节

float类型数值有后缀F或f

3.3.3 char类型

在Java中,char类型描述UTF-16一个代码单元,占2字节

3.3.5 boolean类型

两个值:false和true。整型值和布尔值不能相互转换

3.4 变量与常量

3.4.1 声明变量

  • 在Java中,每个变量都有一个类型
  • 变量名由字母开头并由字母或数字构成的序列。字母包括Unicode字符。变量名大小写敏感,长度没限制
  • 不能使用Java保留字作为变量名

3.4.2 变量初始化

  • 声明一个变量后必须显示初始化,不能使用未初始化的变量的值
  • 在Java中可以将声明放在代码任何位置
  • 在Java中,变量的声明尽可能靠近变量第一次使用的地方

3.4.3 常量

  • 在Java中,使用final指示常量

  • 常量赋值后不能修改,习惯上常量名全大写,用"_"连接

  • 在Java中,希望某常量在一个类多个方法使用,称这些常量为类常量。使用static final声明类常量

3.4.4 枚举类型

  • 变量取值在有限的集合内,使用枚举

3.5 运算符

3.5.1 算术运算符

  • 使用算术运算符"+", “-”, “*”, "/"表示加减乘除运算
  • 参与"/"运算的两个数都是整数,表示整数除法;否则,表示浮点除法
  • 整数求余用"%"表示
  • 整数被0除产生异常,浮点数被0除得到无穷大或NaN

3.5.2 数学函数与常量

  • 平方根:Math.sqrt(x)
  • 幂运算:Math.pow(x, a)
  • 正负整数求余:floorMod

3.5.3 数值类型之间的转换

在这里插入图片描述

当一个二元运算符连接两个值时(例如n + f),先将两个操作数转换为同一类型,然后进行计算。

  • 如果两个操作数有一个是double类型,另一个操作数就会转换为double类型
  • 否则,如果其中一个操作数是float类型,另一个操作数将会转换为float类型
  • 否则,如果其中一个操作数是float类型,另一个操作数将会转换为long类型
  • 否则,两个操作数都转换为int类型

3.6 字符串

3.6.1 子串

String类的substring方法可以提取子串

String greeting = "Hello";
String s = greeting.substring(0, 3);

substring方法的第二个参数是不想复制的第一个位置。

3.6.2 拼接

使用“+”拼接字符串

当将一个字符串与一个非字符串的值进行拼接时,后者会转换为字符串

int age = 13;
String rating = "PG" + age;
System.out.println(rating); // 输出"PG13"

3.6.3 不可变字符串

String类不提供修改字符串中某个字符串的方法。如果要修改,可以提取要保留的子串,再与希望替换的字符拼接。

greeting = greeting.substring(0, 3) + "p!";

由于不能修改Java字符串的单个字符,所以将String类对象称为不可变(immutable)。不过,可以修改字符串变量,让它引用另一个字符串。

3.6.4 检测字符串是否相等

可以使用equals方法检测两个字符串是否相等。

s.equals(t);

如果字符串s与字符串t相等,返回true;否则,返回false。s与t可以是字符串变量,也可以是字符串字面量。

一定不要使用==运算符检测两个字符串是否相等。这个字符串只能确定两个字符串是否存放在同一个位置。

3.6.5 空串与null串

空串""是长度为0的字符串。

判断:

if(str.length() == 0)
//或
if(str.equals(""))

String变量也可以存放一个特殊值,null,表示目前没有对象与该变量关联。

判断:

if(str == null)

有时要检查一个字符串既不是null也不是空串,使用以下条件:

if(str != null && str.length() != 0)

3.6.6 码点与代码单元

length方法返回采用UTF-16编码表示字符串的代码单元数量。

调用s.charAt(n)将返回位置n的代码单元。

在Java中,char类型描述UTF-16编码的一个代码单元。

3.6.7 String API

  • char charAt(int index)

    获取指定位置的字符

  • indexOf(String s)

    返回参数s在指定字符串出现的索引位置。如果没有检索到,返回-1

  • substring(int beginIndex, int endIndex)

    返回指定位置的子字符串

  • trim()

    返回字符串的副本,忽略前导空格和尾部空格

  • replace(String oldChar, String newChar)

    将指定字符串或字符替换为新的字符串或字符

  • startsWith(String prefix)

    判断字符串前缀是否为指定字符串

  • endsWith(string suffix)

    判断字符串后缀是否为指定字符串

  • equals(String otherstr)

    判断两个字符串是否相等

  • compareTo(String otherstr)

    按字典顺序比较两个字符串,该比较基于字符串每个字符的Unicode值

  • split(String regex)
    字符串分割

  • public static String join(CharSequence delimiter, CharSequence… elements)

    返回由elements组成的新String,由指定的delimiter连接起来

3.6.9 构建字符串

  • 使用StringBuilder构建新的String对象。

  • 每次添加内容时,使用append方法

  • 调用toString方法得到String对象

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

常用API

  • StringBuilder()

    构建空的字符串构建器

  • int length()

  • StringBuilder append(String str)

  • StringBuilder append(char c)

  • StringBuilder insert(int offset, String str)

  • StringBuilder insert(int offset, char c)

  • StringBuilder delete(int startIndex, int endIndex)

  • String toString()

3.7 输入与输出

使用标准输入流读取输入。

Scanner in = new Scanner(System.in);
System.out.println("What is your name?");
String name = in.nextLine();
String firstName = in.next();
System.out.println("How old are you?");
int age = in.nextInt();
//nextDouble

常用API

  • Scanner(InputStream in)
  • String nextLine()
  • String next()
  • int nextInt()
  • double nextDouble()
  • boolean hasNext()
  • boolean hasNextInt()
  • boolean hasNextDouble()

3.8 控制流程

3.8.5 多重选择:switch语句

case标签可以是:

  • 类型为char, byte, short, int的常量表示式
  • 枚举常量
  • 字符串字面量

3.10 数组

3.10.1 声明数组

数组初始化

int[] smallPrimes = {2, 3, 5, 7, 11, 13};

3.10.3 for each 循环

增强for循环

for (variable : collection) statement

collection 这一集合必须是数组或一个实现Iterable接口的类对象

3.10.4 数组拷贝

将一个数组所有值拷贝到一个新数组,使用Arrays的copyOf方法

int[] copiedLuckyNumbers = Arrays.copyOf(LuckNumbers, LuckyNumbers.length);

3.10.6 数组排序

使用Arrays类的sort方法

int[] a = new int[100];
Arrays.sort(a)

Math.random方法返回[0, 1)范围的数

4. 对象与类

4.1 面向对象程序设计

4.1.1 类

封装:将数据和行为组合在一个对象中,并对对象使用者隐藏具体的实现方式

4.1.4 类之间的关系

  • 依赖(“uses a”)
  • 聚合(“has a”)
  • 继承(“is a”)

4.4 静态字段与静态方法

使用静态方法的情况:

  • 方法不需要对象状态
  • 方法只需要访问类的静态字段

4.5 方法参数

Java总是按值调用。

4.6 对象构造

4.6.1 重载

多个方法相同名字,不同参数

4.6.3 无参数的构造器

如果写一个类时没有编写构造器,会提供一个无参数构造器,将所有实例字段设置为默认值

4.6.7 初始化块

初始化数据字段的方法:

  • 构造器设置值
  • 声明中赋值
  • 初始化块

调用构造器处理步骤:

  1. 如果构造器第一行调用另一个构造器,则执行第二个构造器
  2. 否则,
    1. 所有数据字段初始化为默认值
    2. 按照在类声明的顺序,执行所有字段初始化方法和初始化块
  3. 执行构造器

4.7 包

4.7.1 包名

用因特网域名逆序形式作为包名

4.7.3 在包中增加类

要将类放入包中,必须将包名字放在源文件开头

package com.horstmann.corejava;

...

如果没有放置package语句,这个类属于无名包(unnamed package)

5. 继承

5.1 类、超类、子类

5.1.1 定义子类

使用extends表示继承

5.1.2 覆盖方法

super.getSalary();

调用超类的getSalary方法

5.1.3 子类构造器

public Manager(String name, double salary, int year, int month, int day) {
super(name, salary, year, month, day);
bonus = 0;
}
  • 使用super调用超类构造器初始化超类的私有字段。
  • 使用super或this调用构造器的语句必须是子类构造器的第一条语句。
  • 如果子类构造器没有显式调用构造器,将自动调用超类的无参构造器。
  • 如果超类没有无参数的构造器,并且在子类的构造器又没有显式调用其他构造器,编译器会报错。
  • 覆盖一个方法的时候,子类方法不能低于超类方法的可见性。

this的两个含义:

  1. 隐式参数的引用
  2. 调用该类的其他构造器

super的两个含义:

  1. 调用超类的方法
  2. 调用超类的构造器

多态:一个对象变量可以指示多种实际类型的现象

动态绑定:运行时能够自动选择适当的方法

5.1.5 多态

子类引用的数组可以转换为超类引用的数组

        //Employee是超类,Manager是子类
        Manager[] managers = new Manager[10];
        Employee[] staff = managers;
        staff[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
        managers[0].setBonus(5000);//ERROR

将一个普通员工加入经理队列,当调用managers[0].setBonus(5000);会调用一个不存在的方法,引发ArrayStoreException异常。

为了不发生这类破坏,所有数组都要牢记创建时的元素类型

5.1.6 理解方法调用

方法调用过程:

  1. 编译器查看对象的声明类型和方法名

  2. 编译器确定方法调用的参数

  3. 如果是private方法,static方法,final方法或者构造器,编译器可以确定调用哪个方法,这称为静态绑定。如果调用方法依赖所引用的对象,在运行时进行动态绑定

  4. 如果采用动态绑定,虚拟机必须调用与所引用对象实际类型对应的方法

    • 每次调用方法要搜索调用的方法,时间开销大
    • 虚拟机预先为每个类计算了一个方法表,列出所有方法的签名和要调用的实际方法,调用方法的时候,虚拟机查找这个表就行了

在运行时,动态绑定的解析过程:

  1. 首先,虚拟机获取所引用对象的方法表
  2. 虚拟机查找所调用的方法
  3. 虚拟机调用这个方法

5.1.7 阻止继承:final类和方法

final类:不能继承该类,类的方法自动成为final,不包括字段

方法声明final:子类不能覆盖这个方法

5.1.8 类之间的强制类型转换

  • 只能在继承层次进行强制类型转换
  • 在强制类型转换前,使用instanceof进行检查
  • 使用子类特有的方法才需要强制类型转换

5.1.9 抽象类

  • 使用抽象类,可以不需要实现一些方法
  • 扩展抽象类两种选择:
    • 保留抽象类部分或所有抽象方法未定义,子类为抽象类
    • 定义所有方法,子类不是抽象类

5.1.10 受保护访问

限制超类的某个方法只允许子类访问,或允许子类方法访问超类某个字段,声明方法或字段为受保护(protected)

4个访问修饰符:

  • private:本类可见
  • default:本包可见
  • protected:本包和所有子类可见
  • public:所有类可见

5.2 Object: 所有类的超类

5.2.1 Object类型的变量

  • Object类型变量可以引用所有类型对象
  • 基本数据类型不是对象
  • 所有数组类型都扩展Object类

5.2.2 equals方法

检测一个对象是否等于另外一个对象

5.3 泛型数组列表

5.4 对象包装器与自动装箱

5.5 参数数量可变的方法

5.6 枚举类

枚举的构造器是私有的

5.7 反射

5.7.1 Class类

Java运行时为所有对象维护一个运行时类型标识。

获取:

  • obj.getClass()
  • Class.ForName(className)
  • T.class

6. 接口、lambda表达式与内部类

6.1 接口

6.1.1 接口的概念

  • 接口的所有方法都是public方法,接口字段总是public static final
  • 实现接口使用关键字implements
  • 可以实现多个接口,不能继承多个抽象类

6.1.6 解决默认方法冲突

如果在接口将一个方法定义为默认方法,然后再超类或另一个接口定义同样的方法,如何解决?

  1. 超类优先。如果超类提供一个具体方法,同名且有相同参数类型的默认方法会被忽略
  2. 接口冲突。如果一个接口提供默认方法,另一个接口提供一个同名且参数类型相同的方法,必须覆盖这个方法解决冲突

6.1.8 Comparator接口

自定义排序规则

6.2 lambda表达式

6.2.3 函数式接口

只有一个抽象方法的接口

6.2.4 方法引用

方法引用:指示编译器生成一个函数式接口的实例,覆盖这个接口的抽象方法来调用给定的方法

三种情况:

  1. object::instanceMethod
  2. Class::instanceMethod
  3. Class::staticMethod

6.3 内部类

  • 内部类:定义在另一个类中的类

6.3.1 使用内部类访问对象状态

  • 内部类的对象会有一个隐式引用,指向实例化对象的外部类对象。通过这个指针,可以访问外部对象的全部状态

6.3.2 内部类的特殊语法规则

外围类引用

OuterClass.this

6.3.4 局部内部类

  • 声明局部类不能有访问说明符(public 或 private)。局部类的作用域被限定在声明这个局部类的块中
  • 局部内部类可以访问局部变量

6.3.7 静态内部类

  • 可以将内部类声明为static,这样不会生成外围类对象的引用
  • 只要内部类不需要访问外围类对象,就应该使用静态内部类

6.5 代理

6.5.1 何时使用代理

代理类:运行时创建类

6.5.2 创建代理对象

使用proxy类的newProxyInstance方法

7. 异常、断言和日志

7.1.1 异常分类

  • 所有异常由Throwable继承而来,分为Error类和Exception

  • Error类:系统内部错误

  • Exception类

    • RuntimeException:编程错误
    • 其他异常:程序没问题,由像IO错误导致的异常
  • 非检查型异常:Error类或RuntimeException类

  • 检查型错误:其他异常

7.1.2 声明检查型异常

throws Exception

方法必须声明所有可能抛出的检查型异常。

7.1.3 如何抛出异常

throw new EOFException();

7.2 捕捉异常

try/catch

7.2.5 try-with-Resources语句

try (Resource res = ...) {
	work with res
}

try块退出时,会调用res.close()

7.4 使用断言

assert condition;
assert condition : expression;

表达式作为消息字符串。

8. 泛型

8.2 泛型类

public class Pair<T>

8.3 泛型方法

public static <T> T getMiddle(T... a) {
	return a[a.length / 2];
}

类型变量放在修饰符(public static)的后面,并在返回类型前面

8.4 类型变量的限定

public static <T extends Comparable> T min(T[] a)...

8.5 泛型代码和虚拟机

8.5.1 类型擦除

  • 没有限定的类型变量,替换为Object
public class pair<T> {
 private T first;
 ...
}

替换为

public class Pair {
	private Object first;
	...
}
  • 用第一个限定来替换类型变量
public class Interval <T extends Comparable & Serializable> implements Serializable {
	private T lower;
	...
}

替换为

public class Interval implements Serializable {
	private Comparable lower;
	...
}

8.5.2 转换泛型表达式

编写一个泛型方法调用,如果擦除返回类型,编译器会插入强制类型转换

8.5.3 转换泛型方法

class DateInterval extends Pair<LocalDate> {
	public void setSecond(LocalDate second) {
		...
	} 
}

class Pair<T> {
	private T second;
	public void setSecond(T newValue) {
		second = newValue;
	}
}

类型擦除后

public void setSecond(LocalDate second) {
	...
}

与Pair继承的setSecond方法

public void setSecond(Object second) {
	...
}

是不同的方法,然而这两个方法不应该不一样。

DateInterval interval = new DateInterval();
Pair<LocalDate> pair = interval;
pair.setSecond(aDate);

我们希望setSecond调用具有多态性。问题在于类型擦除与多态发生冲突。

解决方法:编译器在DateInterval类生成一个桥方法

public void setSecond(Object second) {
	setSecond((LocalDate) second);
}

pair引用会调用桥方法,它会调用DateInterval.setSecond(LocalDate)

如果类型变量是返回值,虚拟机会由参数类型和返回类型共同指定一个方法。

总结:

  • 虚拟机没有泛型,只有普通类和方法
  • 所有类型参数会替换为它们的限定类型或Object类
  • 合成桥方法保持多态
  • 为保持类型安全性,必要时强制类型转换

8.7 泛型类型的继承规则

Pair< S > 和Pair< T >没有任何关系,通过通配符解决

8.8 通配符类型

泛型类型有各种局限,Java提供一种解决方案:通配符类型

8.8.1 通配符概念

Pair<? extends Employee>

表示任何泛型Pair类型,类型参数是Employee子类

8.8.2 通配符的超类型限定

? super Manager

9. 集合

9.1 Java集合框架

9.1.2 Collection接口

public interface Collection<E> extends Iterable<E> {
	boolean add(E element);
	Iterator<E> iterator();
}

9.1.3 迭代器

public interface Iterator<E> {
	E next();
	boolean hasNext();
	void remove();
	...                  
}

9.3 具体集合

9.6 算法

9.6.2 排序与混排

List<String> staff = new LinkedList<>();
Collections.sort(staff);
staff.sort(Comparator.comparingDouble(Employee::getSalary).reversed())

9.6.3 二分查找

i = Collections.binarySearch(c, element);

9.6.6 集合与数组的转换

数组转换为集合

String[] values = {"abc", "efg"};
HashSet<String> staff = new HashSet<>(Arrays.asList(values));

集合转换为数组

String[] newvalues = staff.toArray(new String[staff.size()]);

9.7.4 栈

Stack类

  • 18
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值