Java 是很多人一直在用的编程语言,但是有些 Java 概念是非常难以理解的,哪怕是一些多年的老手,对某些 Java 概念也存在一些混淆和困惑。
所以,在这篇文章里,会介绍四个 Java 中最难理解的四个概念,去帮助开发者更清晰的理解这些概念:
匿名内部类的用法
如何实现同步
匿名内部类匿名内部类又叫匿名类,它有点像局部类(Local Class)或者内部类(Inner Class),只是匿名内部类没有名字,我们可以同时声明并实例化一个匿名内部类。
一个匿名内部类仅适用在想使用一个局部类并且只会使用这个局部类一次的场景。
匿名内部类是没有需要明确声明的构造函数的,但是会有一个隐藏的自动声明的构造函数。
创建匿名内部类有两种办法:
通过继承一个类(具体或者抽象都可以)去创建出匿名内部类
通过实现一个接口创建出匿名内部类
咱们看看下面的例子:
// 接口:程序员 interface Programmer { void develop(); } public class TestAnonymousClass { public static Programmer programmer = new Programmer() { @Override public void develop() { System.out.println("我是在类中实现了接口的匿名内部类"); } }; public static void main(String[] args) { Programmer anotherProgrammer = new Programmer() { @Override public void develop() { System.out.println("我是在方法中实现了接口的匿名内部类"); } }; TestAnonymousClass.programmer.develop(); anotherProgrammer.develop(); } }从上面的例子可以看出,匿名类既可以在类中也可以在方法中被创建。
之前我们也提及匿名类既可以继承一个具体类或者抽象类,也可以实现一个接口。所以在上面的代码里,我创建了一个叫做 Programmer 的接口,并在 TestAnonymousClass 这个类中和 main() 方法中分别实现了接口。
Programmer除了接口以外既可以是一个抽象类也可以是一个具体类。
抽象类,像下面的代码一样:
public abstract class Programmer { public abstract void develop(); }具体类代码如下:
public class Programmer { public void develop() { System.out.println("我是一个具体类"); } }OK,继续深入,那么如果 Programmer 这个类没有无参构造函数怎么办?我们可以在匿名类中访问类变量吗?我们如果继承一个类,需要在匿名类中实现所有方法吗?
public class Programmer { protected int age; public Programmer(int age) { this.age = age; } public void showAge() { System.out.println("年龄:" + age); } public void develop() { System.out.println("开发中……除了异性,他人勿扰"); } public static void main(String[] args) { Programmer programmer = new Programmer(38) { @Override public void showAge() { System.out.println("在匿名类中的showAge方法:" + age); } }; programmer.showAge(); } }构造匿名类时,我们可以使用任何构造函数。上面的代码可以看到我们使用了带参数的构造函数。
匿名类可以继承具体类或者抽象类,也能实现接口。所以访问修饰符规则同普通类是一样的。子类可以访问父类中的 protected 限制的属性,但是无法访问 private 限制的属性。
如果匿名类继承了具体类,比如上面代码中的 Programmer 类,那么就不必重写所有方法。但是如果匿名类继承了一个抽象类或者实现了一个接口,那么这个匿名类就必须实现所有没有实现的抽象方法。
在一个匿名内部类中你不能使用静态初始化,也没办法添加静态变量。
匿名内部类中可以有被 final 修饰的静态常量。
匿名类的典型使用场景:临时使用:我们有时候需要添加一些类的临时实现去修复一些问题或者添加一些功能。为了避免在项目里添加java文件,尤其是仅使用一次这个类的时候,我们就会使用匿名类。
UI Event Listeners:在java的图形界面编程中,匿名类最常使用的场景就是去创建一个事件监听器。比如:
button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { } });上面的代码中,我们通过匿名类实现了 setOnClickListener 接口,当用户点击按钮的时候,就会触发我们实现的 onClick 方法。
多线程Java 中的多线程就是利用多个线程共同完成一个大任务的运行过程,使用多线程可以最大程度的利用CPU。
使用多线程的使用线程而不是进程来做任务处理,是因为线程比进程更加轻量,线程是一个轻量级的进程,是程序执行的最小单元,并且线程和线程之间是共享主内存的,而进程不是。
线程生命周期正如上图所示,线程生命周期一共有六种状态。我们现在依次对这些状态进行介绍。
New:当我们构造出一个线程实例的时候, 这个线程就拥有了 New 状态。这个状态是线程的第一个状态。此时,线程并没有准备运行。