Java基础学习笔记

本文最后更新于:32 分钟前

Java类与对象

三大特点:封装,继承,多态

常用的类和方法

1.String类,StringBuffer类,StringBuilder

三种类都是用来创建字符串的,但是后两个操作字符串效率更高(显著高于String类),且节省内存。StringBuilder类线程不安全效率较高,而StringBuffer类线程安全效率较低。

2.Scanner

常用于标准输入,例如:

1
2
Scanner scanner = new Scanner(System.in);
String s = scanner.next(); //next方法一定要用String类接收输入内容,nextInt方法要用int型接收

3.Date类,SimpleDateFormat

前者用于显示当前时间,后者用于显示为设定格式。例如:

1
2
3
4
Date d = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
String format = sdf.format(d);
System.out.println(d.getTime());

4.Math

顾名思义,与数学有关的类。下面总结几个常用方法:

1
2
3
random()  //生成随机数
floor() //向下取整
round() //向上取整

方法

1.compareTo方法

compareTo 方法用于将 Number 对象与方法的参数进行比较。可用于比较 Byte, Long, Integer等。

该方法用于两个相同数据类型的比较,两个不同类型的数据不能用此方法来比较。

  • 如果指定的数与参数相等返回0。
  • 如果指定的数小于参数返回 -1。
  • 如果指定的数大于参数返回 1。
  • 如果要比较Object类型的对象,则需要实现Comparable接口,并重写compareTo方法。

2.sort方法

该方法在Arrays类中,使用前需要导入java.util.Arrays包,默认是给数组按照升序排序。当然,也可以给数组按照降序排序,只需要给sort方法的第二个形参传入Collections.reverseOrder()方法,或者实现Comparator接口并重写compare方法。

静态

Java语言中,我们使用static关键字来表示静态。静态方法、静态属性会在编译前在内存中加载,所以静态方法中无法直接调用非静态方法。静态属性只能通过类名.静态属性名的方式调用,而静态方法可以直接在静态方法中调用,或者用类名.静态方法名的方式调用。非静态方法只能通过对象.方法名调用。

方法重载

Java允许同一个类中定义多个同名方法,只要它们的形参列表不同即可。如果同一个类中包含了两个或两个以上方法名相同的方法,但形参列表不同,这种情况被称为方法重载。例如,以下代码是对构造器的重载(不写构造器时,默认调用无参构造器):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
	public Person(){
super();
// this.money=100;
System.out.println("构造器1");
}

public Person(int i){
// this();
super(i);
System.out.println("构造器2");
}

public Person(String name,int age,String sex){
// this(8888);
super(name,age,sex);
this.name=name;
this.age=age;
this.sex=sex;

this和super关键字

this关键字表示对象内对类的当前实例的引用,它只能在实例的上下文中使用。

super关键字用于引用直接父类对象,访问父类的构造方法、普通方法和属性。引用父类构造器时是super(),引用父类方法时是super.方法名(),括号里传递的是父类方法中的实参。

需要注意的是,thissuper都要放在方法内的第一行,所以两者只能选一个。

final关键字

相当于C++中的const关键字,表示常量,可用来修饰类、方法和变量。修饰类时,表示这个类不能被继承;修饰方法时,表示这个方法不能被重写;修饰变量时,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

代码块(了解即可)

静态代码块:作用和静态属性、静态方法类似,都是在编译前把代码加载进内存。

非静态代码块:在new对象时加载进内存。

多态性

多态性,指对象的多种形态。例如,AnimalDogCat的父类,则后者继承了前者。但是,一般会有多个子类继承同一个父类,所以为了方便实例化,一般写成以下形式:

1
2
Animal a = new Dog();
Animal b = new Cat();

在调用属性或方法时,属性看父类,方法看子类。例如AnimalDog两个类均含有属性id和方法call(),则a.id调用的是Animal类的id属性,a.call()调用的是Dog类的call()方法。

当类型发生强制转换时,只能是父类的对象强制转换成子类的,相同级别的类不能转换。例如,Dog d = (Dog) a是合法的,而Cat c = (Cat) a会报错。

使用关键字instanceof可以判断一个对象是否是一个类(或接口、抽象类、父类)的实例。例如:a instanceof Animal

匿名类和匿名对象

Java中可以实现一个类中包含另外一个类,且不需要提供任何的类名直接实例化。主要是用于在我们需要的时候创建一个对象来执行特定的任务,可以使代码更加简洁。匿名类通常继承一个父类或实现一个接口。

匿名类是不能有名字的类,它们不能被引用,只能在创建时用new语句来声明它们。例如:

1
2
3
4
5
6
7
8
9
class outerClass {
void dome(){
sout("xxxx");
}
// 定义一个匿名类
object1 = new Type(parameterList) {
// 匿名类代码
};
}

匿名对象就是没有明确的给出名字的对象,是对象的一种简写形式。一般匿名对象只使用一次,而且匿名对象只在堆内存中开辟空间,而不存在栈内存的引用。如果一个对象只需要使用唯一的一次,就可以使用匿名对象,匿名对象还可以作为实际参数传递。以上面的代码为例,实现一个匿名对象:

1
2
3
4
5
6
7
8
9
public class dome{
main(){
new outerClass.dome(); //实现匿名对象
/**
*不再是以前的outerClass oc = new outerClass();
*oc.dome();
*/
}
}

内部类

内部类分为四种:1.成员内部类 2.静态内部类 3.方法内部类 4.匿名内部类

成员内部类只能作为附属存在,不能独立存在。使用方法和成员属性类似,修饰符也和普通类相同,定义方式和具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A{
public int c = 1;
main(){
A a = new A(); //先实例化外部类
B b = a.new B(); //再实例化内部类,注意要有外部类的对象.new xx()
b.BB();
}
class B{
public int c = 2;
public void BB(){
sout(A.this.c); //调用外部类的属性c,注意不是a.this.c,因为作用域
sout(this.c); //调用内部类的属性c
}
}
}

方法内部类,指的是写在方法体里面的类。例如:

1
2
3
4
5
6
public void show(){
class Dome{
//代码
}
Dome d = new Dome(); //调用方式
}

匿名内部类可以在定义一个类的同时对其进行实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类。这里是直接把它写在了方法的实参里面。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Animal{
main(){
Animal a = new Animal(); //这里括号后面也可以写匿名内部类
a.call(new Dog(){ //如果Dog类有父类,还可以写父类名
@Override
public void call(){
super.call();
});
}
public void call(Dog dog){
dog.call();
}
}
class Dog{
public void call(Dog dog){
sout("汪汪叫");
}
}

注意:匿名内部类很重要,实际编程中经常用到!

抽象类和抽象方法

抽象方法:没有方法体的方法。定义方式:

1
public abstract hello();

抽象类:含有抽象方法的类,不能被实例化。例如:

1
2
3
4
public abstract class Hello{
public abstract hello();
public String hello;
}

接口

可以理解为一种特殊的类,即只有抽象方法的类,但它其实不是类。例如:

1
2
3
public interface Hello{
public abstract hello();
}

它克服了Java无法多继承的缺陷,实现接口一般使用implements关键字,而不是extends关键字。

异常处理

异常可分为两种类型:运行时异常和非运行时异常。捕获异常可以让程序在遇到错误时能够继续执行,而不是报错并中断执行。程序每次只会抛出一种异常。

try…catch…finally语句

try语句中一般写要执行的代码,catch语句用于捕获异常。这里给出一段演示代码:

1
2
3
4
5
6
7
8
try{
int []a=new int[10];
a[11]=1;
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}catch(Exception e){
sout(e.getMessage());
}

其中printStackTracegetMessage方法都用于输出异常信息。第一个catch语句中的内容是一种具体类型的异常(即子类异常),第二个catch语句中的内容是所有类型异常的父类。当两者共存时,父类异常必须在子类异常后面,就像上面代码写的那样。如果子类捕获到了异常,则父类不会捕获到。

finally代码块表示不管是否抛出或捕获异常,都会执行里面的代码。因为不管是否发生异常finally都会执行,因此我们可以在finally代码块中执行关闭连接、关闭文件和释放线程的的操作。

throw和throws关键字

throw关键字是在方法体内抛出异常并处理,throws关键字是在方法体外抛出异常并处理。如果程序中存在很多个方法,那么可以在每个方法后面抛出异常,并在main方法集中处理,来减少每个方法体中try...catch...语句的数量。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
main(){
try{
dome1();
dome2();
dome3();
}catch(Exception e){
//处理异常
}
}
public void dome1 throws Exception{
sout("dome1");
}
public void dome2 throws Exception{
sout("dome2");
}
public void dome3{
sout("dome3");
throw Exception;
}

自定义异常类型

从API可知,自定义异常需要继承RuntimeException类。使用该异常时,直接使用匿名类即可。


Java基础学习笔记
https://rookieterry.github.io/2023/03/30/Java基础学习笔记/
作者
HackerTerry
发布于
星期四, 三月 30日 2023, 11:15 晚上
许可协议