目录
概述:
Java的基本单位是类,类中包含五个部分:变量、方法、构造器、初始化块、内部类
第一章、Java类的五个成员之一:变量
1.1)变量分类
①变量分类
①变量根据数据类型分类
两类:Java中的变量根据数据类型分为两类:基本数据类型变量和引用数据类型变量。
1、基本数据类型变量:基本数据类型是Java语言内置的数据类型,用于存储简单的数值。基本数据类型包括整型、浮点型、字符型和布尔型。
public class PrimitiveExample {
public static void main(String[] args) {
int num = 10; // 整型变量
double salary = 1000.50; // 浮点型变量
char grade = 'A'; // 字符型变量
boolean isStudent = true; // 布尔型变量
System.out.println("Number: " + num);
System.out.println("Salary: " + salary);
System.out.println("Grade: " + grade);
System.out.println("Is student: " + isStudent);
}
}
2、引用数据类型变量:引用数据类型是指存储对象引用的变量,而不是对象本身。引用数据类型包括类、接口、数组等。
public class ReferenceExample {
public static void main(String[] args) {
String str = "Hello, Java!"; // 字符串对象引用
int[] numbers = {1, 2, 3, 4, 5}; // 整型数组对象引用
System.out.println("String: " + str);
System.out.print("Numbers: ");
for (int num : numbers) {
System.out.print(num + " ");
}
}
}
②变量根据变量定义位置分类
两类:变量根据定义位置的不同分为全局变量(成员变量)和局部变量。
1、全局变量(也称为成员变量)是在类中声明的变量,其作用域为整个类。全局变量可以是实例变量(非静态变量)或类变量(静态变量)。
2、局部变量:在方法、构造函数或代码块内部声明的变量,其作用域仅限于声明它的方法、构造函数或代码块。局部变量在方法、构造函数或代码块执行时创建,执行结束时销毁。
public class Example {
// 全局变量(实例变量)
String globalVar = "This is a global variable";
public void exampleMethod() {
// 局部变量
int localVar = 10;
System.out.println("Local variable: " + localVar);
System.out.println("Global variable: " + globalVar);
}
public static void main(String[] args) {
Example obj = new Example();
obj.exampleMethod();
System.out.println(obj.globalVar);
}
}
②成员变量分类
两类:成员变量分为类变量和实例变量。
Java成员变量和类变量的区别:
实例变量(非静态变量):只能通过对象名调用(通过对象实例访问)。实例变量是属于类的每个对象实例的变量,存储在堆内存。 每个对象都有自己的一组实例变量副本,它们在对象创建时被初始化。实例变量可以。
public class Person {
String name; // 实例变量
int age; // 实例变量
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "Alice";
person1.age = 25;
Person person2 = new Person();
person2.name = "Bob";
person2.age = 30;
}
}
类变量(静态变量):静态变量也称为类变量,可以直接通过类名调用。也可以通过对象名调用,这个变量属于类,存储在方法区栈中的静态区。静态变量只有一个副本,会被所有类的实例共享。可以直接通过类名访问静态变量,而不需要创建对象。
static int staticVar; // 静态变量,只会初始化一次
③成员变量和局部变量的区别
①成员变量直接定义在类中,整个类可以使用。
②局部变量定义在方法块中,必须赋一个初始值,只有在方法中才可以使
③内存位置不一样。成员变量位于堆当中。局部变量位于栈当中。
④生命周期不同。成员变量随着对象创建而诞生,随着对象被回收消失。局部变量随着方法进栈诞生,随着方法出栈消失。
2.1)成员变量详解
①成员变量作用域/权限修饰符
对于类的成员(包括成员变量和成员方法)而言,其能否被其他类所访问,取决于该成员的修饰词。
①其中public成员变量可以被任何类访问和使用。可以通过类名.成员变量名的方式来访问public成员变量。
②protected成员变量只能在类内部和子类中使用。在子类中,可以通过super关键字来访问父类的protected成员变量。
③空着不写:同类中,同包中
④private成员变量只能在类内部使用,要访问private成员变量必须通过类提供的公共方法来访问。
②成员变量和成员属性的区别
①属性的官方定义:属性是指get或者set方法名,去掉get或者set后,把剩余的部分首字母改为小写后,即为这个类的属性。
②图中紫色P为类的属性,黄色f为成员变量。从图中可以看出age是成员变量,size和name为类的属性,不是类的成员变量。
③成员变量初始化方式
①直接无值初始化,会给一个默认值
class Ver_1
{
//成员变量初始化时不赋值会有默认值
private boolean flag; // false
private int _int; // 0
private char _char; //'0000'
private float _float; //Default value: 0.0
private long _long; //Default value: 0
private double _double; //Default value: 0.0
//引用类型默认值是 null
}
②直接赋值初始化
class Ver_1
{
//成员变量,定义在类里
int a = 10;
}
③构造方法初始化,在进入构造函数之前,默认初始化num为0,进入构造函数后赋值为20。
public class Ver_1{
int num ;
public Ver_1(){
num = 20;
}
}
④成员变量初始化顺序
①非静态成员变量,在构造函数之前初始化,并且按定义顺序初始化。
②静态代码块和静态成员变量执行顺序和代码中出现的顺序有关。
③静态成员变量优先于非静态成员变量,静态初始化只在Class对象第一次创建时发生一次。下面搬运了一段代码举例:
public class StaticInitialization {
public static void main(String[] args) {
System.out.println("Creating new Cupboard() in main");
new Cupboard();
System.out.println("Creating new Cupboard() in main");
new Cupboard();
t2.f2(1);
t3.f3(1);
}
static Table t2 = new Table();
static Cupboard t3 = new Cupboard();
}
class Bowl{
Bowl(int i){
System.out.println("Bowl"+i);
}
void f(int i){
System.out.println("f"+i);
}
}
class Table{
static Bowl b1 = new Bowl(1);
Table(){
System.out.println("Table()");
b2.f(1);
}
void f2(int i){
System.out.println("f2("+i+")");
}
static Bowl b2 = new Bowl(2);
}
class Cupboard{
Bowl b3 = new Bowl(3);
static Bowl b4 = new Bowl(4);
Cupboard(){
System.out.println("Cupboard()");
b4.f(2);
}
void f3(int i){
System.out.println("f3("+i+")");
}
static Bowl b5 = new Bowl(5);
}
输出结果如下:
Bowl1
Bowl2
Table()
f1
Bowl4
Bowl5
Bowl3
Cupboard()
f2
Creating new Cupboard() in main
Bowl3
Cupboard()
f2
Creating new Cupboard() in main
Bowl3
Cupboard()
f2
f2(1)
f3(1)
第二章、Java类的五成员之二:方法
①方法是代码语句的集合体,这些语句集合起来实现一些特定功能。
②联系生活我们可以这样理解:一个个代码是文章中的词语,词语(代码)组成句子(代码语句);句子(代码语句)组成段落(方法);段落(方法)组成文章(类)。
2.1)Java中方法的定义
自定义方法的五要素:修饰符,返回值类型,方法名,参数列表,方法体
[修饰符1 修饰符2 …] 返回值类型 方法名(形式参数列表){
Java语句
}
如下:
public static int myMethod(int num1, int num2) {
return num1 > num2 ? num1 : num2;
}
①方法的修饰符
修饰符的作用:
1)如public,访问权限修饰符的作用:public是公开的意思,代表其他类和方法可以访问(使用)被public修饰的方法。
2) 如static,静态修饰符的作用:static是静态的意思,修饰后可直接访问;不被static修饰,就需要用对象来访问了。
3)如final,final有最终的意思,final修饰的方法为最终的方法,该方法不能被重写;
②方法的返回值类型
1)无返回值的类型 void:void表示调用方法后无返回数据。return后面没有写返回数据时,仅仅表示方法体的结束。
2)有返回值:如果方法中需要得出的结果(返回值),。那么定义方法时必须根据结果指定返回数据的数据类型。返回值类型可以是基础类型数据,也可以是引用类型数据并且在方法执行的最后一句必须是return语句
例子:无返回值方法
public static void m1() {
System.out.println("方法有五要素组成"); //①
/*
在没有返回值的方法内部,如果有需要也可以定义return关键字,
语法没有任何问题,但是使用的情况并不多。
*/
return;
}
例子:有返回值方法
public static String m2() {
//自定义方法内部发起对别的自定义方法的调用
m1();
return "method";
//错误: 无法访问的语句
//分析:在同一作用域中,return语句的后面不能定义任何代码,因为永远不可能被执行到
//System.out.println("我可以被执行吗?");
}
③方法名
1)方法名可以自己定义,也就是自己取名字需要尽量做到望文生义。
2)命名规范:首字母小写。多个单词时第一个单词首字母小写,后续单词首字母大写。
④方法的参数列表
1)方法中可以带参数也可以不带参数
2)形参:形式参数,定义方法时写在括号里的都是形参。被调用时才会被分配内存空间,调用结束就会释放,属于局部变量。
3)实参:实际参数,可以是常量、变量或表达式。在调用有参方法时,方法名后面括号中的参数就是“实际参数”,实参变量对形参变量的数据传递是“值传递”,也就是只能由实参传递给形参,而不能由形参传递给实参。
例子:无参数方法
public static String m2() {
//自定义方法内部发起对别的自定义方法的调用
m1();
return "method";
}
例子:有参数方法
//有参方法
public static int m4(int num1, int num2) {
return num1 > num2 ? num1 : num2;
}
⑤方法体
1)声明方法时大括号和大括号中的语句内容。
public class Test {
public static void main(String[] args) {
System.out.println("{大括号和它之间的内容就是main方法的方法体}");
}
}
2.2)方法的重载和重写
①方法的重载
满足方法重载的要求:
1).重载的方法必须被定义在同一个类中
2).重载方法的名字必须相同
3).重载方法的形参列表必须不同(类型、个数、位置)
例子:方法的重载
4)重载是静态绑定,编译时就根据实参类型确定了调用哪个方法。
//自定义方法:计算两个整数的和值
public static void sum(int a,int b){
System.out.println("两个整数求和");
}
//自定义方法:计算两个小数的和值
public static void sum(double d1,double d2){
System.out.println("两个小数求和");
}
//自定义方法:计算三个整数的和值
public static void sum(int num1,int num2,int num3){
System.out.println("三个整数求和");
}
//上述三个sum方法彼此之间构成方法的重载现象
②方法的重写
方法的重写
①重写(override):也称覆盖。重写是子类对父类非静态,非private,非final,非构造方法的实现过程进行重新编写,重写的目的在于根据对象的类型不同而表现出多态,而静态方法不需要创建对象就可以使用。没有了对象,重写所需要的“对象的类型”也就没有存在的意义了。
②修饰符,返回值类型,方法名,参数列表要完全一致,返回值(JDK7以后,被重写的方法返回值类型可以不同,但是必须是具有父子关系的)即外壳不变,核心重写。
③重写的方法不能使用限制更严格的访问权限修饰符。比如被重写的方法修饰符是 protected,那么重写的方法只能是 protected 或者 public修饰。
④重写后的方法不能抛出比父类中更高级别的异常。
⑤子类中通过 super 关键字来调用父类中被重写的方法。
⑥分四点
1.子类继承普通类,并非一定要重写父类方法
2.子类继承抽象类,子类是抽象类,不要求重写父类方法。子类是普通类要重写全部抽象方法。
3.子接口继承父接口。子接口可以继承父接口的所有常量和抽象方法,子接口还可以继承其他父接口也就是可以扩展父接口的方法;
4.如果是一个子抽象类,可以部分或全部实现父接口的方法;如果子类是具体类,则要求子类一定要实现父接口中定义的所有方法(接口中的所有方法均为抽象方法)。
public abstract class A{
abstract void show();
public void func(){
System.out.println("父类普通方法");
}
}
class B extends A {
public static void main(String[] args) {
B b = new B();
b.show();
b.func();
}
@Override
void show(){
System.out.println("重写父类的抽象方法");
};
@Override
public void func(){
System.out.println("子类重写父类普通方法");
}
}
//打印结果
//重写父类的抽象方法
//子类重写父类普通方法
2.3)Java中方法的调用
太长了直接点链接看这篇==》方法之间的调用
第三章、Java类的五成员之三:构造器
3.1)什么是构造器,构造器特点
构造器是处于Java类中的一个方法,最大的作用创建对象时执行初始化。
①构造方法名不能自定义必须和类名相同。普通的方法首字母小写后续单词字母大写。
②构造器可以哟访问权限修饰符但是不能有final,,static,,abstract,synchronized,native修饰符。
②没有返回值和返回类型,也不需要void。
③构造器在创建对象时执行初始化
class Citizen
{ //成员属性
String name;
MyDate birth;
//构造方法
public Citizen(String n,MyDate b){
name = n;
birth = b;
}
}
3.2)构造器的重载(方法重载)
①缺省构造器指没有人为写构造方法时,系统隐式生成的空参构造器,当我们初始化对象不给对象的属性赋值时将调用此缺省构造方法。
②非缺省构造器指人为显示定义的构造方法,当我们初始化对象需要给对象的属性赋值时将调用此非缺省构造方法,当我们写了有参构造的时候,系统将不会再生成空参构造器必须我们手动写出来(显示定义)。
③二者构成重载现象
class Citizen
{ //成员属性
String name;
MyDate birth;
//构造方法
public Citizen(String name,MyDate birth){
this.name = name;
this.birth = birth;
}
public Citizen(){
//空参构造,与有参构造构成了方法重载
}
}
3.3)执行构造方法之前
在执行构造函数中的代码之前,先要执行隐式三步:
a)super():调用父类构造函数
b)给对象空间中的非静态成员变量显示赋值
c)执行构造代码块
创建对象的过程中执行优先级:
静态代码块和静态成员变量执行顺序和代码中出现的顺序有关,静态成员变量优先于非静态成员变量,非静态成员变量优先于构造代码块,构造代码块优先于构造函数之前初始化
也就是:
静态代码块=静态成员变量>非静态成员变量>构造代码块>构造函数中代码
构造函数结束出栈,对象创建完成。
3.4)构造器中的this关键字
this用法
①this在构造器中,代表当前构造器正在创建的对象的内存地址,同时使用this在构造方法内部调用本类重载的构造方法必须只能在首行位置进行调用 否则将导致编译错误
class Teacher
{ String name;
int age;
//两个参数构造方法
public Teacher(String name,int age){
//this.name = name; //this. 的方式,如果没注释就得报错,因为this(name)必须首行
this(name); //this(name); 调用重载构造方法的方式
this.age = age;
}
//一个参数构造方法
public Teacher(String name){
this(); // this(); //调用重载构造方法的方式
this.name = name; //this. 不用放首行
System.out.println("一个参数构造...this=" + this); //② 同一个正在被创建对象的地址
}
//无参构造
public Teacher(){
//如果this("徐老师",32,);取消注释,会错误: 递归构造器调用,构造方法之间相互调用不能形成闭合回路
//this("徐老师",32,);
System.out.println("空参数构造...this=" + this); //① 正在被创建对象的地址
}
public void printInfo(){
System.out.println("姓名:" + name + ",年龄:" + age + ",籍贯:" +
address + "...this=" + this);//③ 已经创建完成对象的地址
}
}
②this在非静态方法中:this代表已经创建完成的对象,指向正在执行方法的类的实例。(谁调用我,我指向谁)
package test_this;
class Person
{ String name;
int age;
public Person(String n,int a){
//① 此处的this记录的是当前正在被创建Person对象的内存地址
System.out.println("构造方法...this=" + this);
name = n;
age = a;
}
public Person(){ }
public void printInfo(){
System.out.println("姓名:" + name + ",年龄:" + age + "...this=" + this); //③ 此处this记录的是已经创建完毕Person对象的内存地址
}
public static void main(String[] args)
{
Person p = new Person("张三",30);
System.out.println(p); //② 此处的p记录的是已经创建完毕Person对象的内存地址
p.printInfo();
}
}
/*打印结果
构造方法...this=test_this.Person@3d8c7aca
test_this.Person@3d8c7aca
姓名:张三,年龄:30...this=test_this.Person@3d8c7aca
*/
③用来区分成员变量和局部变量。
class Student
{ String name;
private int age;
char sex;
public Student(String name,int age,char sex){
this.name = name;
this.age = age;
this.sex = sex;
}
public Student(){ }
public int getAge(){
return this.age;
}
public void setAge(int age){
this.age = age;
}
public void printInfo(){
String name = "lili";
int age = 18;
System.out.println("姓名:" + this.name + ",年龄:" + this.age + ",性别:" + this.sex);
}
public static void main(String[] args)
{ String name = "lili";
int age = 18;
Student s = new Student("韩梅梅",19,'女');
s.printInfo();
}
}
// 打印结果 姓名:韩梅梅,年龄:19,性别:女
④静态方法不能使用this关键字,因为静态方法不属于类的实例,所以this也就没有什么东西去指向。
3.5)构造器中的super关键字
super关键字用法:
①super在普通方法中:用这个关键字去执行被重载的超类中的非静态方法,使用super.func()去调用超类中被重载的方法。
ps:重写父类方法的时候可以在子类方法体里直接super.父类方法,直接把父类方法拿过来用然后再添加其他代码,达到复用的目的。
class Father
{ public void func(){
System.out.println("Father...func");
}
}
//---------------------------------分割--------------------------------
class Son extends Father
{ public void func(){
System.out.println("Son...func");
}
public void test(){
//func();
super.func();
}
}
②super关键字在构造方法:子类构造方法首行隐式的有super()用来接受父类成员变量,先调用父类构造再调用子类构造。 对super的调用必须是构造器中的第一个语句。this() 和 super() 不能同时存在,因为他们都要写在构造函数的第一行。
class Person
{
//属性
String name;
int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public Person(){ }
}
//------------------分割--------------------------------------
class Worker extends Person
{
//方式一:显示定义在构造方法内部调用super(...)构造
public Worker(String name,int age){
super(name,age);
}
//方式二:在Person类中有空参构造,本类的空参构造隐式的有super();
public Worker(){
//super();//可以不写
}
}
③父类和接口中如果都定义了相同名字的默认方法,子类继承父类的同时实现了该接口,默认执行父类中的方法,这是类优先原则,如果想使用接口中的方法:接口名.super.方法名。
④两个接口中都定义了相同名字的默认方法,子类同时实现两个接口,这时候编译器报错,需要选择一下具体用哪个,或者用接口名.super.方法名来选择,再或者直接全部重写。
public interface Inter2 {
//默认方法1
public default void method(){
System.out.println("Inter2...method");
}
//默认方法2
public default void func(){
System.out.println("Inter2...func");
};
//抽象方法
void show();
}
//-------------------------------分割------------------------------
public interface Inter3 {
//默认方法1
public default void method(){
System.out.println("Inter3...method");
}
//默认方法2
public default void func(){
System.out.println("Inter2...func");
};
//抽象方法
void show();
}
//-------------------------------分割------------------------------
/* 接口冲突问题:
* 多个接口内部都定义了相同名字的默认方法,类同时去实现这多个接口,
* 用接口名.super.方法名来选择,再或者直接全部重写。
*/
public class InterImpl2 implements Inter2, Inter3 {
@Override//重写默认方法
public void method() {
// Inter2.super.method();
// Inter3.super.method();
System.out.println("都不适合,完全重写...");
}
@Override//重写默认方法
public void func() {
Inter2.super.func();
// Inter3.super.func();
// System.out.println("都不适合,完全重写...");
}
@Override//重写抽象方法
public void show() {
System.out.println("sbsbsb");
}
}
第四章、Java类的五成员之四:代码块
4.1)静态代码块
① 静态代码块static修饰的代码块,直接写在类中的代码块。
在类加载的时候执行,只执行一次,通常用于初始化静态变量,它比main还先执行,执行顺序是静态代码块–构造方法
public class Test {
static {
System.out.println("类加载的时候执行");
}
}
4.2)构造代码块
①构造代码块在构造方法中,构造代码块跟创建对象实例有关(和类加载无关),每创建一个对象实例,就加载一次。(可以看作是构造器的补充,构造器被调用了,构造代码快就会被调用)
②创建对象的过程中执行优先级:
静态代码块和静态成员变量执行顺序和代码中出现的顺序有关,静态成员变量优先于非静态成员变量,非静态成员变量优先于构造代码块,构造代码块优先于构造函数之前初始化
也就是:
静态代码块=静态成员变量>非静态成员变量>构造代码块>构造函数中代码
public class Test {
static {
System.out.println("静态代码块类加载的时候执行");
}
public Test(){
{
System.out.println("构造代码块定义在构造方法中,不需要加static修饰");
}
}
}
4.3)局部代码块
①不同的是,局部代码块只能写在局部位置(方法中),可以用来限制部分代码使用范围。
public class Test {
static {
System.out.println("类加载的时候执行");
}
public Test(){
{
System.out.println("定义在构造方法中,不需要加关键字修饰");
}
}
public void testFunc(){
{
System.out.println("局部代码块定义在方法中,不需要加关键字修饰");
}
}
}
第五章、Java类的五成员之五:内部类
5.1)内部类
将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类
①成员内部类
将一个类定义在另一个类里面。
①类TestInner像是类Test的成员,Test称为外部类。如下:编译会产生两个文件:Test.class和Test$TestInner.class。
class Test {
class TestInner{
}
}
//编译会产生两个文件:Test.class和Test$TestInner.class。
②成员内部类可以无条件访问外部类的所有成员属性和成员方法(包括private成员和静态成员)。
③外部类想访问成员内部类的成员,必须先创建一个成员内部类的对象,再通过指向这个对象的引用来访问:
class Circle {
private double radius = 0;
public Circle(double radius) {
this.radius = radius;
getDrawInstance().drawSahpe(); //必须先创建成员内部类的对象,再进行访问
}
private Draw getDrawInstance() {
return new Draw();
}
class Draw { //内部类
public void drawSahpe() {
System.out.println(radius); //外部类的private成员 }
}
}
④没有使用static关键字修饰的成员内部类就是非静态成员内部类,里面只能定义非静态成员;而且非静态成员内部类的对象,必须依赖于外部类的对象存在,也就是说,如果要创建成员内部类的对象,前提是必须存在一个外部类的对象
publicclass Test {
public static void main(String[] args) {
//第一种方式:
Outter outter = new Outter();
Outter.Inner inner = outter.new Inner(); //必须通过Outter对象来创建
//第二种方式:
Outter.Inner inner1 = outter.getInnerInstance();
}
}
class Outter {
private Inner inner = null;
public Outter() {
}
public Inner getInnerInstance() {
if(inner == null)
inner = new Inner();
return inner;
}
class Inner {
public Inner() {
}
}
}
②方法内部类
将一个类定义一个方法里面
①方法内部类对象不能使用该内部类所在方法的非final局部变量。因为方法的局部变量位于栈上,在方法内创建的内部类对象可能存在于堆中!因为不能保证局部变量的生命周期和方法内部类对象的一样长,所以内部类对象不能使用它们。
②方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化。
class Test {
public void Func(){
class TestInner{
}
}
}
③匿名内部类
使用匿名内部类能够在实现父类或者接口中的方法情况下同时产生一个相应的对象,但是前提是这个父类或者接口必须先存在才能这样使用。
①匿名内部类不能有构造方法。
②匿名内部类不能定义任何静态成员、静态方法。
③匿名内部类不能是public,protected,private,static。
④只能创建匿名内部类的一个实例。
⑤一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
⑥因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
package anonymous;
class Father{
public void func(){
System.out.println("Father...func");
}
}
interface Inter{
public abstract void method();
}
public class TestAnonymous_1 {
public static void main(String[] args) {
//创建匿名内部类的同时直接创建子类对象,重写父类方法,调用func();
new Father(){
@Override
public void func() {
System.out.println("重写fun...");
}
}.func();
//创建匿名实现类的同时直接创建实现类对象,实现method
new Inter(){
@Override
public void method() {
System.out.println("实现method...");
}
}.method();
}
}
④静态内部类
①使用static关键字修饰的成员内部类就是静态内部类,也被称为顶级嵌套类。
②静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。静态嵌套类仅能访问外部类的静态成员和方法。
③在静态方法中定义的内部类也是StaticNested Class,这时候不能在类前面加static关键字,静态方法中的StaticNested Class与普通方法中的内部类的应用方式很相似,它除了可以直接访问外部类中的static的成员变量,还可以访问静态方法中的局部变量,但是,该局部变量前必须加final修饰符。
class Outer{
static class Inner{}
}
class Test {
public static void main(String[] args){
Outer.Inner n = new Outer.Inner();
}
}
5.2)匿名内部类与Lambda表达式
Lambda经常用来和匿名内部类比较
但注意:
1.Lambda表达式虽然简洁,用()->就可以代替整个匿名内部类,但只能用于函数式接口(有仅只有一个抽象方法的接口)。匿名内部类却可以用于接口,抽象类或者普通类。举个函数式接口Runnable接口的例子:
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("这是匿名内部类里传了个Runnable的实现类对象");
}
}).start();
用Lambda写一下
new Thread(() -> System.out.println("好家伙这么简洁")).start();