2024-12-23
Android/Java
00

目录

一. 类与文件
二. 关键字
final
static
this & super
interface
三. 继承
四. 多态
五. 内部类
六. 异常
七. 访问权限
八. 线程
方式一:继承Thread类
方式二:实现Runnable接口
方式三:实现Callable接口,通过Future获取结果
三种创建线程方式对比

一. 类与文件

  1. Java文件中类的规则

    • 一个Java文件可以包含多个类class。
    • 只能有一个public类,且文件名必须与public类名相同。这一点和matlab函数模块相似。
    • 使用javac编译后,会生成多个类名.class文件。运行时,使用java 类名执行具有主函数的类。
  2. Jar文件的创建与执行

    • 多个class文件可以打包成一个jar文件。
    • 使用java -jar test.jar执行前,需要在MANIFEST.MF中定义Main-Class属性,例如:Main-Class: test.someClassName
  3. 包(package)

    • 包用于组织相关类、接口及其他包。
    • 包对应的目录结构以/表示层级,例如 E:/Java/workspace/Demo/bin/p1/p2/Test.java
    • 包名表示层级关系,例如 p1.p2.Test 表示包 p1.p2 下的 Test 类。
  4. import 导入

    • import语句只能导入包中的类或接口,不能导入整个包。
    • 通常使用通配符*导入包下所有类或接口,例如:import java.util.*;

二. 关键字

final

  • 修饰类:类不能被继承。
  • 修饰方法:方法不能被重写。
  • 修饰变量:变量成为常量,只能赋值一次。

覆盖规则

  1. 子类覆盖父类方法时,子类方法的访问权限要大于或等于父类。
  2. 静态方法只能覆盖静态方法。
  3. 父类方法添加final后,子类不能覆盖。
  4. 子类方法可以使用super.method调用父类方法,但不能调用父类的private方法。

static

  1. 静态成员(静态变量和静态方法)

    • 随类加载而加载,且优于对象存在。
    • 被所有对象共享,可以通过类名调用(例如:类名.成员)。
  2. 静态代码块

    • 随类加载而执行,并且只执行一次,用于类的初始化。
    • 静态代码块执行优先于构造函数和对象初始化。
  3. 注意事项

    • 静态方法只能访问静态成员。
    • 静态方法中不能使用thissuper关键字。
    • 主函数(main方法)是静态的。main一般是public static void main(String[] args)

this & super

  • this

    • 代表当前类对象的引用。
    • 可用于区分成员变量和同名的局部变量。
  • super

    • 代表父类的引用。
    • 用于调用父类的构造函数、方法或成员变量。

interface

  • 接口中的成员默认是public static final(变量)和public abstract(方法)。
  • 类与接口之间实现关系用implements。接口之间可用extends继承,且支持多继承。
  • 抽象类提供部分实现,而接口只能定义抽象方法。这是抽象类的优势。

三. 继承

  • 子类构造函数默认调用父类的无参构造函数(super();)。
  • 如果父类没有无参构造函数,子类必须使用super(参数列表)调用父类构造函数。
  • 如果子类构造函数使用this调用本类其他构造函数,则不能同时使用super,因为二者必须在第一行。

四. 多态

  1. 成员变量

    • 编译时:使用引用类型变量所属类的成员变量。
    • 运行时:也是使用引用类型变量所属类的成员变量。
  2. 成员函数

    • 编译时:使用引用类型变量所属类的方法。
    • 运行时:使用对象实际类型的方法。
  3. 静态方法

    • 编译和运行时都是使用引用类型变量所属类的静态方法。

五. 内部类

  • 成员内部类:直接访问外部类成员,外部类访问需创建内部类对象。
  • 静态内部类:创建时不依赖外部类对象。

示例:

java
outer.inner in = new outer().new inner(); in.show();

静态内部类:

java
outer.inner in = new outer.inner(); in.show();
java
class Outer { int num = 3; class Inner { int num = 4; void show() { int num = 5; System.out.println(Outer.this.num); } } void method() { new Inner().show(); } }
  • 局部内部类:只能访问被final修饰的局部变量。
  • 匿名内部类:即匿名子类对象,用于简化代码。

示例:

java
abstract class Demo { abstract void show(); } class Outer { int num = 4; public void method() { new Demo() { void show() { System.out.println("show ..." + num); } }.show(); } } class InnerClassDemo4 { public static void main(String[] args) { new Outer().method(); } }

错误示例:

java
Object obj = new Object() { public void show() { System.out.println("show run"); } }; obj.show();

因为Object类没有show()方法。

典型使用场景:函数参数为接口类型时,使用匿名内部类。

java
interface Inter { void show1(); void show2(); } class InnerClassDemo5 { public static void main(String[] args) { show(new Inter() { public void show1() {} public void show2() {} }); } public static void show(Inter in) { in.show1(); in.show2(); } }

六. 异常

  • 函数抛出的异常需要声明或捕获,未声明的必须捕获。
  • 调用抛出异常的函数需要捕获或继续抛出,未处理会编译失败。
  • 使用catch捕获异常,无法解决时使用throws延续异常处理。

自定义异常:继承自ExceptionRuntimeException

七. 访问权限

类间访问权限:

public protected default private
同一类中 Y Y Y Y
同一包中 Y Y Y N
子类中 Y Y N N
不同包中 Y N N N

八. 线程

方式一:继承Thread类

java
class SubThread extends Thread { public void run() { System.out.println("hahah"); } } SubThread s = new SubThread(); s.start();

方式二:实现Runnable接口

  1. 实现Runnable接口。
  2. 覆盖run方法。
  3. 通过Thread类创建线程对象,并传递Runnable对象。
  4. 调用start方法。

好处:分离任务和线程实现,避免单继承限制。

java
class ThreadImpl implements Runnable { public void run() { System.out.println("runnable run"); } } Thread t = new Thread(new ThreadImpl()); t.start();

方式三:实现Callable接口,通过Future获取结果

  1. 实现Callable接口的call方法,有返回值。
  2. 使用FutureTask包装Callable对象。
  3. 使用Thread创建并启动线程。
  4. 通过FutureTask的get方法获取返回值。
java
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableThreadTest implements Callable<Integer> { public static void main(String[] args) { CallableThreadTest ctt = new CallableThreadTest(); FutureTask<Integer> ft = new FutureTask<>(ctt); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " 的循环变量i的值" + i); if (i == 20) { new Thread(ft, "有返回值的线程").start(); } } try { System.out.println("子线程的返回值:" + ft.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } @Override public Integer call() throws Exception { int i = 0; for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } return i; } }

三种创建线程方式对比

Runnable、Callable接口方式

  • 优势:可以继承其他类,适合多个线程处理同一资源。
  • 劣势:编程复杂,需要Thread.currentThread()获取当前线程。

Thread继承方式

  • 优势:编写简单,直接用this获取当前线程。
  • 劣势:无法再继承其他类。
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!