JavaSE:类与对象

1.什么是面向对象?

以做饭举例
按照每个步骤依次进行的就是面向过程
面向过程形式的做饭注重的是做饭的过程
在这里插入图片描述
而我们去找个厨师,让他包揽整个做饭的步骤,我们只需要提供基础的内容就可以,厨师做饭是为了给我服务的,所以他面向的对象是我
面向对象方式来进行处理,就不关注洗做饭的过程

在这里插入图片描述

2.类

2.1认识一下类

在java中定义类时需要用到class关键字

语法格式:

// 创建类
class 类名{
field; // 字段(属性) 或者 成员变量
method; // 行为 或者 成员方法
}

class为定义类的关键字
类中的属性是用来描述类的,也被称为成员变量
类中的行为是用来说明类有哪些功能的,也被称为成员方法

2.2类的定义格式

class Person {
    //成员变量
    String name;
    int age;
    //方法-》行为
    public void eat(){
        System.out.println(name+"正在吃饭");
    }
    public void sleep(){
        System.out.println(name+"正在睡觉");
    }
    public void play(){
        System.out.println(name+"正在玩");
    }
}

注意事项:

  • 类名注意采用大驼峰定义
  • 成员前写法统一为public.
  • 此处写的方法不带 static 关键字.

2.3类要注意的问题

public修饰的类必须要和文件名相同,不然不能加public在这里插入图片描述
如果硬要加public就要去src新建一个文件
在这里插入图片描述
注意事项:

  1. 一般一个文件当中只定义一个类
  2. main方法所在的类一般要使用public修饰
  3. public修饰的类必须要和文件名相同
  4. 不要轻易去修改public修饰的类的名称,如果要修改,通过开发工具修改

3.类的实例化

对象.成员和对象.方法可以访问对象的内容

3.1怎样去实例化一个对象

定义了一个类,就相当于在计算机中定义了一种新的类型
用类类型创建对象的过程,称为类的实例化,在java中采用new关键字,配合类名来实例化对象。

public static void main(String[] args) {
        Person person1 = new Person();
        person1.name="张三";
        person1.age=18;
        person1.eat();

        Person person2 = new Person();
        person2.name="李四";
        person2.age=20;
        person2.sleep();
    }

在这里插入图片描述

注意事项:

  • new 关键字用于创建一个对象的实例.
  • 使用 . 来访问对象中的属性和方法.
  • 同一个类可以创建对个实例.

3.2类实例化后的内存关系

当我们实例化一个对象后,只会把类中的成员/属性实例化到对象中,而方法并不会在对象中存储,当调用某个对象的方法时,还是会在栈上创建函数栈帧去进行计算。
在这里插入图片描述
注意:

  1. 创建的对象只会存储成员/属性到对象中,方法不会出现在对象中
  2. 当调用对象的方法时,还是会从栈中创建栈帧去计算

3.3实例化做了什么

  1. 为新的对象开辟内存
  2. 调用构造方法

4.类和对象(重点)

  1. 类只是一个模型一样的东西,用来对一个实体进行描述,限定了类有哪些成员.
  2. 类是一种自定义的类型,可以用来定义变量.
  3. 一个类可以实例化出多个对象,实例化出的对象 占用实际的物理空间,存储类成员变量
  4. 打个比方,类实例化出对象就像现实中使用建筑设计图建造出房子,类就像 是设计图
    只设计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象才能实际存储数据,占用物理空间

5.this引用

5.1为什么要有this引用

class Date {
    public int year;
    public int month;
    public int day;

    public void setDay(int y, int m, int d) {
        year = y;
        month = m;
        day = d;
    }

    public void printDate() {
        System.out.println(year + "/" + month + "/" + day);
    }
}

public class TestDemo {
    public static void main(String[] args) {
        // 构造三个日期类型的对象 d1 d2 d3
        Date d1 = new Date();
        Date d2 = new Date();
        Date d3 = new Date();
        // 对d1,d2,d3的日期设置
        d1.setDay(2022,4,15);
        d2.setDay(2022,4,16);
        d3.setDay(2022,4,17);
        // 打印日期中的内容
        d1.printDate();
        d2.printDate();
        d3.printDate();
    }
}

在main方法中利用Date这个类创建了三个对象,然后分别赋值输出

但有个问题

形参名不小心与成员变量名相同:
假如我将类中的setDay方法改成如下,那方法知道那个是成员变量那个是形参名吗,到最后打印就会出问题,如果要区分那就需要this引用了

此时方法中的成员变量优先

public void setDay(int year, int month, int day){
	year = year;
	month = month;
	day = day;
}

在这里插入图片描述

5.2什么是this引用

this本质上是一个引用,this代表当前对象的引用,在类中成员方法可以调用成员变量,而为了更加确切的表明,在这个方法中的这个变量指的是类中的成员变量,我们就需要加上this去标识

1.调用当前对象的成员变量
下面的代码中,this引用就代表d引用指向的对象,d.setDay也就让this知道它应该指向和d一样的对象

class Date {
    public int year;
    public int month;
    public int day;

    public void setDay(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
}
public static void main(String[] args) {
	Date d = new Date();
	d.setDay(2020,9,15);
	d.printDate();
}

这样我们修改后就可以正常打印了
在这里插入图片描述
2.this调用当前对象的成员方法
这样下面的代码this就能自己打印信息了
在这里插入图片描述
3.this调用当前对象的其他构造方法
下面会讲
4. this不能使用在静态成员方法中
在这里插入图片描述

5.3this引用的特证

  1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
  2. this只能在"成员方法"中使用
  3. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象
  4. this不能使用在静态成员方法中



6.对象的构造及初始化

6.1如何初始化对象

如果没有初始化一个局部变量,那么会报错

public static void main(String[] args) {
	int a;
	System.out.println(a);
}
// Error:(26, 28) java: 可能尚未初始化变量a

初始化对象需要使用构造方法

public static void main(String[] args) {
	Date d = new Date();//这就是构造方法
	d.printDate();
	d.setDate(2021,6,9);
	d.printDate();
}
// 代码可以正常通过编译

有两个问题

1.如果每次创建完对象初始化都需要调用成员方法,是不是很麻烦
2.局部变量必须初始化,为什么对象中的成员变量不初始化可以使用

6.2构造方法

构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次

public class Date {
	public int year;
	public int month;
	public int day;
	// 构造方法:
	// 名字与类名相同,没有返回值类型,设置为void也不行
	// 一般情况下使用public修饰
	// 在创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次
	public Date(int year, int month, int day){
		this.year = year;
		this.month = month;
		this.day = day;
		System.out.println("Date(int,int,int)方法被调用了");
	}
	public void printDate(){
		System.out.println(year + "-" + month + "-" + day);
	}
	public static void main(String[] args) {
		// 此处创建了一个Date类型的对象,并没有显式调用构造方法
		Date d = new Date(2021,6,9); // 输出Date(int,int,int)方法被调用了
		d.printDate(); // 2021-6-9
	}
}

这样每次创建对象时,只需要在构造方法里放入一些初识值就可以相当于初识化对象了

注意:构造方法的作用就是对对象中的成员进行初始化,并不负责给对象开辟空间

6.3构造方法的特性

  1. 名字必须与类名相同
  2. 没有返回值类型,设置为void也不行
  3. 创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次)
  4. 构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)
public class Date {
	public int year;
	public int month;
	public int day;
	// 无参构造方法
	public Date(){
	this.year = 1900;
	this.month = 1;
	this.day = 1;
	}
	// 带有三个参数的构造方法
	public Date(int year, int month, int day) {
		this.year = year;
		this.month = month;
		this.day = day;
	}
	public void printDate(){
		System.out.println(year + "-" + month + "-" + day);
	}
}	

上述两个构造方法:名字相同,参数列表不同,因此构成了方法重载。

  1. 如果用户没有显式定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的。
public class Date {
	public int year;
	public int month;
	public int day;
	public void printDate(){
		System.out.println(year + "-" + month + "-" + day);
	}
}
	public static void main(String[] args) {
		Date d = new Date();
		d.printDate();
	}

上述Date类中,没有定义任何构造方法,编译器会默认生成一个不带参数的构造方法。
注意:一旦用户定义,编译器则不再生成。
所以要想好要不要定义构造方法

public class Date {
	public int year;
	public int month;
	public int day;
	public Date(int year, int month, int day) {
	this.year = year;
	this.month = month;
	this.day = day;
	}
	public void printDate(){
		System.out.println(year + "-" + month + "-" + day);
	}
	public static void main(String[] args) {
	// 如果编译器会生成,则生成的构造方法一定是无参的
	// 则此处创建对象是可以通过编译的
	// 但实际情况是:编译期报错
	Date d = new Date();
	d.printDate();
}
/*
Error:(26, 18) java: 无法将类 extend01.Date中的构造器 Date应用到给定类型;
需要: int,int,int
找到: 没有参数
原因: 实际参数列表和形式参数列表长度不同
*/
  1. 构造方法中,可以通过this调用其他构造方法来简化代码
public class Date {
	public int year;
	public int month;
	public int day;
	// 无参构造方法--内部给各个成员赋值初始值,该部分功能与三个参数的构造方法重复
	// 此处可以在无参构造方法中通过this调用带有三个参数的构造方法
	// 但是this(1900,1,1);必须是构造方法中第一条语句
	public Date(){
		//System.out.println(year); 注释取消掉,编译会失败
		this(1900, 1, 1);
		//this.year = 1900;
		//this.month = 1;
	/	/this.day = 1;
	}
	// 带有三个参数的构造方法
	public Date(int year, int month, int day) {
		this.year = year;
		this.month = month;
		this.day = day;
	}
}

this调用当前对象的其他构造对象是this(),但是你要知道,你不能在当前构造对象中调用自己,这样会死循环无限递归下去,需要有两个及以上的构造方法才能调用,也要知道调用完后还会回到当前的构造方法继续执行,并且this()必须放在方法中的第一行,如果有多个this()那就只能选择一个
1.this()必须在构造方法中调用
2.this()必须在构造方法中的第一行
3.this()不能在本构造方法中调用自己形成环,这样会死循环

注意:

  • this(…)必须是构造方法中第一条语句
  • 不能形成环
public Date(){
	this(1900,1,1);
}
public Date(int year, int month, int day) {
	this();
}
/*
无参构造器调用三个参数的构造器,而三个参数构造器有调用无参的构造器,形成构造器的递归调用
编译报错:Error:(19, 12) java: 递归构造器调用
*/

6.4默认初始化

在6.1中提出了一个问题,为什么局部变量使用的时候必须初始化,而成员变量不需要呢
要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情:

Date d = new Date(2022,5,2);

在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:

  1. 检测对象对应的类是否加载了,如果没有加载则加载
  2. 为对象分配内存空间
  3. 处理并发安全问题
    比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突
  4. 初始化所分配的空间
    即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:在这里插入图片描述
  5. 设置对象头信息
  6. 调用构造方法,给对象中各个成员赋值

6.5构造方法快捷键

右击点击"Generate"然后点击"Constructor",只后选中想要初始化的成员/属性然后点击OK系统会自动给你创建对应的构造方法
在这里插入图片描述

7.初始化成员的方法总结

  1. 定义成员/属性/字段的时候初始化
  2. 定义成员/属性/字段的时候不初始化(默认值)
  3. 在类外调用成员/属性/字段进行赋值
  4. 通过构造方法初始化
  5. 调用对象的方法对成员/属性/字段进行初始化

8.private实现封装

private/ public 这两个关键字表示 “访问权限控制” .

  • 被 public 修饰的成员变量或者成员方法, 可以直接被类的调用者使用.
  • 被 private 修饰的成员变量或者成员方法, 不能被类的调用者使用.

也就是说被private修饰后只能在类中使用被修饰的成员变量或者方法

class Person {
	public String name = "张三";
	public int age = 18;
}
class Test {
	public static void main(String[] args) {
		Person person = new Person();
		System.out.println("我叫" + person.name + ", 今年" + person.age + "岁");
	}
}
// 执行结果
我叫张三, 今年18
在这里插入代码片
  • 这样的代码导致类的使用者(main方法的代码)必须要了解 Person 类内部的实现, 才能够使用这个类. 学习成本较高
  • 一旦类的实现者修改了代码(例如把 name 改成 myName), 那么类的使用者就需要大规模的修改自己的代码, 维护成本较高.
class Person {
	private String name = "张三";
	private int age = 18;
	public void show() {
		System.out.println("我叫" + name + ", 今年" + age + "岁");
	}
}
class Test {
	public static void main(String[] args) {
		Person person = new Person();
		person.show();
	}
}
// 执行结果
我叫张三, 今年18
  • 此时字段已经使用 private 来修饰. 类的调用者(main方法中)不能直接使用. 而需要借助 show 方法. 此时类的使用者就不必了解 Person 类的实现细节.
  • 同时如果类的实现者修改了字段的名字, 类的调用者不需要做出任何修改(类的调用者根本访问不到 name, age这样的字段).

注意事项

  • private 不光能修饰字段, 也能修饰方法
  • 通常情况下我们会把字段设为 private 属性, 但是方法是否需要设为 public, 就需要视具体情形而定. 一般我们希
    望一个类只提供 “必要的” public 方法, 而不应该是把所有的方法都无脑设为 public.

8.1private修饰后成员的修改和访问

可以用get或者set去对类中被private修饰的成员进行间接的访问或修改
在这里插入图片描述

8.2private修饰构造方法

不准private修饰构造方法,因为构造方法都需要在别的类去调用,private修饰后会有问题
暂时理解为不行,其实private修饰构造方法的意思是这个类不允许你创建对象

9.static成员

总的一句说:静态的不能直接访问非静态的(也就是说创建对象去通过对象去访问非静态的内容是可以的)
不包含this

9.1static修饰成员变量

在Java中,被static修饰的成员,称之为静态成员,也可以称为类成员,其不属于某个具体的对象,是所有对象所共享的

创建对象后static的内容不会存到对象里,很多不会修改的成员变量可以用static修改成静态成员变量,这样创建对象后不会浪费堆上的空间存储不会修改的内容,因为static修饰的成员变量存储在静态区,只有一份

静态成员也被称之为类变量

静态成员不仅能使用类名.静态成员变量访问还能使用对象.静态成员变量去访问

类名.静态成员变量 
对象.静态成员变量

【静态成员变量特性】

  1. 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
  2. 既可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
  3. 类变量存储在方法区当中
  4. 生命周期伴随类的一生(即:随类的加载而创建,随类的卸载而销毁)
class Student{
	public String name;
	public String gender;
	public int age;
	public double score;
	public static String classRoom = "317";
}

public static void main(String[] args) {
	// 静态成员变量可以直接通过类名访问
	System.out.println(Student.classRoom);
	Student s1 = new Student("Li leilei", "男", 18, 3.8);
	Student s2 = new Student("Han MeiMei", "女", 19, 4.0);
	Student s3 = new Student("Jim", "男", 18, 2.6);
	// 也可以通过对象访问:但是classRoom是三个对象共享的
	System.out.println(s1.classRoom);
	System.out.println(s2.classRoom);
	System.out.println(s3.classRoom);
}

static修饰的静态成员变量/类变量不能在方法中定义
static定义的变量是类变量,属于类
在这里插入图片描述

9.2 static修饰成员方法

不管是static修饰的方法还是其他方法,只要用到了类就需要在上方导入包,导入对应的类

Java中,被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的。静态成员一般是通过静态方法来访问的

静态方法不仅能使用类名.静态方法访问还能使用对象.静态方法去访问

类名.静态方法
对象.静态方法

成员方法可以调用静态成员变量普通成员变量
静态方法只能调用静态成员变量(其实在静态方法中创建对象,使用其他类去调用非静态成员是可以做到的,这种访问方式是对象去访问了不是本方法的问题)

成员方法可以调用静态方法
静态方法不能调用成员方法(创建对象去对象.成员方法是可以做到访问的,这种访问方式是对象去访问了不是本方法的问题)

【静态方法特性】

  1. 不属于某个具体的对象,是类方法
  2. 可以通过对象调用,也可以通过类名.静态方法名(…)方式调用,更推荐使用后者
  3. 静态方法是存储在方法区的
  4. 不能在静态方法中访问任何非静态成员变量
public int age;

public static String ageUp(){
	age += 1;
	return age;
}
// 编译失败:Error:(35, 9) java: 无法从静态上下文中引用非静态 变量 age
  1. 静态方法中不能调用任何非静态方法,因为非静态方法有this参数,在静态方法中调用时候无法传递this引用,但非静态的方法可以调用静态的方法(其实在静态方法中创建对象,使用其他类创建的对象去调用非静态成员是可以做到的)
    在这里插入图片描述

10.public和private与default修饰成员(重点)!!!

public是公共访问权限:

  • 可以跨同一个包中类中的其他类(非public的类),也可以跨同一个包中不同类,也可以跨包,也可以在不同非包类中访问
  • 但前提是,如果被public修饰的成员不在本类中,需要导包后创建对象才能访问!
  • 但是要是加上了static修饰就变为静态对象,可以不用创建对象去访问,直接导包后用类名去访问,也可以导包后继续用对象.静态成员去访问

private是私有访问权限:

  • 只能在自己类中使用,不能跨类,不能跨包,即使是同一个类中的其他类也不行

default是包访问权限:

  • 如果包中类的成员前面不写修饰词,那他就默认是包访问权限
  • 这种成员可以在本包中的任何地方被访问,前提是创建对象!!!
  • 但是要是加上了static修饰就变为静态对象,可以不用创建对象去访问,直接用类名去访问,也可以继续用对象.静态成员去访问

11.代码块

11.1 代码块概念以及分类

使用{} 定义的一段代码称为代码块。根据代码块定义的位置以及关键字,又可分为以下四种:

  • 普通代码块
  • 构造块
  • 静态块
  • 同步代码块(多线程时再去学习)

11.2普通代码块

普通代码块:定义在方法中的代码块

public class Main{
	public static void main(String[] args) {
	{ //直接使用{}定义,普通方法块
		int x = 10 ;
		System.out.println("x1 = " +x);
	}
	int x = 100 ;
	System.out.println("x2 = " +x);
	}
}
// 执行结果
x1 = 10
x2 = 100

这种用法很少见

11.3 构造代码块

构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量

lass Person{
    String name;

    {
        System.out.println("实例代码块");
    }
	//实例代码块
    static {
        System.out.println("静态代码块");
    }

    Person(){
        System.out.println("创建成功");
    }
}


public class TestDemo {
    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println("==========");
        Person person2 = new Person();
    }
}

11.4静态代码块

使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量

lass Person{
    String name;

    {
        System.out.println("实例代码块");
    }
	//静态代码块
    static {
        System.out.println("静态代码块");
    }

    Person(){
        System.out.println("创建成功");
    }
}


public class TestDemo {
    public static void main(String[] args) {
        Person person1 = new Person();
        System.out.println("==========");
        Person person2 = new Person();
    }
}

在实行顺序上是先执行静态代码块,然后是实例代码块,最后是构造方法,并且只要加载类创建对象了,不管创建了几次对象静态代码块只能执行一次!!
在这里插入图片描述

代码块注意事项

注意事项

  • 静态代码块不管生成多少个对象,其只会执行一次
  • 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
  • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次合并
  • 实例代码块只有在创建对象时才会执行

12.对象的打印

当我们调用

public class Person {
	String name;
	String gender;
	int age;
	public Person(String name, String gender, int age) {
		this.name = name;
		this.gender = gender;
		this.age = age;
	}
}


public static void main(String[] args) {
	Person person = new Person("Jim","男", 18);
	System.out.println(person);
	}
}
// 打印结果:day20210829.Person@1b6d3586

如果想要默认打印对象中的属性该如何处理呢?答案:在对应的类中重写toString方法即可。
因为在println调用时源码调用了toString,我们在类重现toString,仅限于println这个类中的内容时,才会出现修改的内容,哪怕改一个输出的类都不会发生其他改变
在这里插入图片描述

public class Person {
	String name;
	String gender;
	int age;
	public Person(String name, String gender, int age) {
		this.name = name;
		this.gender = gender;
		this.age = age;
	}
@Override
	public String toString() {
		return "[" + name + "," + gender + "," + age + "]";
	}
public static void main(String[] args) {
	Person person = new Person("Niu","男", 18);
	System.out.println(person);
	}
}
// 输出结果:[Niu,男,18]



13.内部类

public class OutClass {
	// 成员位置定义:未被static修饰 --->实例内部类
	public class InnerClass1{
	
	}

	// 成员位置定义:被static修饰 ---> 静态内部类
	static class InnerClass2{
	
	}

	public void method(){
		// 方法中也可以定义内部类 ---> 局部内部类:几乎不用
		class InnerClass5{
		
		}
	}
}

分类:

  1. 实例内部类:未static修饰的成员内部类(重点)
  2. 静态内部类:被static修饰的成员内部类(重点)
  3. 局部内部类
  4. 匿名内部类

创建内部类编译后生成的.class文件回是这样的:
外部类$内部类.class
在这里插入图片描述

13.1实例内部类

即未被static修饰的成员内部类

public class OutClass {
    private int a;
    static int b;
    int c;

    public void methodA() {
        a = 10;
        System.out.println(a);
    }

    public static void methodB() {
        System.out.println(b);
    }

    // 实例内部类:未被static修饰
    class InnerClass {
        int c;

        public void methodInner() {
            // 在实例内部类中可以直接访问外部类中:任意访问限定符修饰的成员
            a = 100;
            b = 200;
            methodA();
            methodB();
            // 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类自己的
            c = 300;
            System.out.println(c);
            // 如果要访问外部类同名成员时候,必须:外部类名称.this.同名成员名字
            OutClass.this.c = 400;
            System.out.println(OutClass.this.c);
        }
    }

    public static void main(String[] args) {
        //创建内部类的对象需要先创建外部类对象,再去用 外部类.内部类 引用变量 = 外部类引用.内部类 去创建
        OutClass out = new OutClass();
        OutClass.InnerClass inner = out.new InnerClass();

        //书上经常写成这样
        OutClass.InnerClass inner2 = new OutClass().new InnerClass();
    }
}

如果要在内部类中定义静态成员必须要被static final修饰,因为静态要提前加载,先要加载外部类,所以这里就要有限制
在这里插入图片描述
内部类当中不能创建静态方法,因为静态要提前加载,先要加载外部类,所以这里就要有限制
在这里插入图片描述
如何访问内部类和外部类同名的成员变量
内部类:this.成员变量
外部类:外部类类名.this.成员变量

public class OutClass {
    int a = 10;

    // 实例内部类:未被static修饰
    class InnerClass {
        public int a=20;
        static final int d = 10;
        public void print(){

            System.out.println(OutClass.this.a);
            System.out.println(this.a);
        }
    }
}
public class TestDemo {
    public static void main(String[] args) {
        OutClass out = new OutClass();
        OutClass.InnerClass inner = out.new InnerClass();
        inner.print();
    }
}
//打印出来的是 10  20

外部类不能直接访问内部类的成员和方法,如果要访问就要先创建内部类对象
在这里插入图片描述

注意事项:

  1. 外部类中的任何成员都可以被在实例内部类方法中直接访问
  2. 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
  3. 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员 来访问
  4. 实例内部类对象必须在先有外部类对象前提下才能创建
  5. 实例内部类的非静态方法中包含了一个指向外部类对象的引用也就是:外部类.this
  6. 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象
  7. 内部类不能创建静态方法,静态成员也只能用final static修饰才能使用

13.2静态内部类

public class OutClass {
	private int a;
	static int b;
	public void methodA(){
		a = 10;
		System.out.println(a);
	}
	public static void methodB(){
		System.out.println(b);
	}



// 静态内部类:被static修饰的成员内部类
	static class InnerClass{
		public void methodInner(){
		// 在内部类中只能访问外部类的静态成员
		// a = 100; // 编译失败,因为a不是静态成员变量
		b =200;
		// methodA(); // 编译失败,因为methodB()不是静态成员方法
		methodB();
	}
}





public static void main(String[] args) {
	// 静态内部类对象创建 & 成员访问
	OutClass.InnerClass innerClass = new OutClass.InnerClass();
	innerClass.methodInner();
	}
}

注意事项:

  1. 在静态内部类中只能访问外部类中的静态成员
  2. 创建静态内部类对象时,不需要先创建外部类对象

13.3局部内部类

public class OutClass {
	int a = 10;
	public void method(){
		int b = 10;
		// 局部内部类:定义在方法体内部
		// 不能被public、static等访问限定符修饰
		class InnerClass{
		public void methodInnerClass(){
		System.out.println(a);
		System.out.println(b);
			}
		}
		// 只能在该方法体内部使用,其他位置都不能用
		InnerClass innerClass = new InnerClass();
		innerClass.methodInnerClass();
		}
	public static void main(String[] args) {
		// OutClass.InnerClass innerClass = null; 编译失败
	}
}

注意事项:

  1. 局部内部类只能在所定义的方法体内部使用
  2. 不能被public、static等修饰符修饰
  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值