文章目录
说到成员就是三样东西:成员变量、构造方法、成员方法。
一、成员变量
1)概述
接口中的成员变量只能是 常量
,默认会使用 public static final
去修饰。
这里默认的意思就是:就算你没写,Java也会帮你加上。为什么是这样的呢?其实是有原因的。
思考:多个子类的共有属性
你觉得它是抽取到哪里的?是抽取到接口当中的吗?
并不是的,多个子类的共有属性
它是抽取到 父类
中的,不会抽取到接口里面。
因此接口中是不会有类似于:name、age等这些成员变量的。
而且接口是一种规则,规则是不能发生改变的。因此接口中的成员变量都是 常量
,会使用 final
去修饰。
static
的目的其实就是我可以方便的进行调用,用 接口名.常量名
就行了。
public
表示公共的,表示在所有的地方都可以去使用接口中的常量。
2)其他课程
很多课程中是这样的验证的
System.out.println(Inter.a); // 证明它是用 static 修饰的
Inter.a = 10; // 这里报错,证明它是用 final 修饰的。
我们来查看报错原因:Cannot assign a value to final variable 'a'
(无法为最终变量“a”赋值)
![image-20240418081645948](https://img-blog.csdnimg.cn/img_convert/6dc6f0912686fced15326e70bf5eca20.png)
这么解释也可以,如果想要看到最本质的情况,那还是需要用到内存分析工具。
接下来就带着大家看一下,这个接口加载到内存后,它到底是什么样的。
3)通过内存分析工具
证明
为了掩饰它的效果,这里还需要新建一个 InterImpl
,接口的实现类。
Inter.java
package com.itheima.a02interfacedemo2;
public interface Inter {
// 默认是 public static final 修饰的
int a = 10;
// 默认是 public abstract 修饰的
void method();
}
Inter.java
package com.itheima.a02interfacedemo2;
public class InterImpl implements Inter{
@Override
public void method() {
System.out.println("method");
}
}
Test.java
package com.itheima.a02interfacedemo2;
import java.util.Scanner;
/*
成员变量
只能是常量,默认修饰符:public static final
构造方法
没有
成员方法
只能是抽象方法,默认修饰符:public abstract
*/
public class Test {
public static void main(String[] args) {
//创建实现类对象并调用方法
InterImpl ii = new InterImpl();
ii.method();
// 内存分析工具它有一个前提:程序不能停。
// 程序一旦执行完毕,就无法通过 内存分析工具 再看它内存中的情况的。
Scanner sc = new Scanner(System.in);
sc.next();
}
}
内存分析工具了解一下就行了,你只需要知道我在干什么就行了。后面会有一个单独的章节去说它的。
接下来执行测试类。
程序开始运行后,点击下面的 Terminal
,然后输入 jps
,此时我就能看到当前 Test测试类
在运行的时候的 ID。
然后输入 jhsdb hsdb
,这样就可以把内存分析工具
打开。
File ——> Attach to HotSpot process...
(Attach
:连接;HotSpot
:虚拟机的名字)
输入刚刚测试类的ID:21728
,然后点击 OK
即可
![image-20240418083920279](https://img-blog.csdnimg.cn/img_convert/2195790697822fe64730a44a306e22b7.png)
在这我们不需要去看对象里面是什么东西,如果需要看对象里面有什么,就需要点击 Tool ——> Memory Viewer
。
但是我现在不想看对象里面,而是想看字节码文件中的信息,那我就点击第一个就行了。Class Browser
。
在弹出的窗口中,可以去找我们想要的字节码文件,但是太多了。当然也可以在上面的搜索框搜索。
我们这里就来搜 InterImpl
这个实现类,然后回车即可。
可以发现已经找出来了这个实现类。
![image-20240418084408447](https://img-blog.csdnimg.cn/img_convert/f6bb2d3062cb69f8e4eb0382e2df3183.png)
点击一下,在这可以看见,它有一个 Super Class
。
Super Class
指的就是它爹,它爹是 Object
。
![image-20240418084837593](https://img-blog.csdnimg.cn/img_convert/660d374c4059e77c6e93c3bfe1635d12.png)
再往下,看到 Interfaces
,这里就表示这个类实现的所有接口。
但现在我只实现了一个接口:Inter
,因此在这里它罗列的就是 Inter
。
![image-20240418084928339](https://img-blog.csdnimg.cn/img_convert/978ad148bb0a7b848d19b13723e7f51f.png)
用鼠标点击一下接口,此时它在内存中的一些字节码信息,你就都能看见了。
首先先来看 Fields
(属性)。
此时就能很明确的看清:属性是由 public static final
来修饰的,但是我的代码中明没有加上这三个修饰词。
也就是说 public static final
这三个修饰符是Java默认为我们加上的。
二、构造方法
1)概述
构造方法最简单,两个字:没有。
在接口当中,它是没有构造方法的,因为接口不能创建对象,而且接口中也不需要给子类的成员变量去赋值,因此接口用不着构造方法。
既然用不到,Java在设计接口的时候,就没有设计构造方法。
2)通过内存分析工具
证明
在通过 内存分析工具
看构造方法之前,先来看一下 InterImpl
这个实现类,这个实现类中我们并没有写构造。
但是 Java 会自动的给它添加一个无参构造。
![image-20240418090407245](https://img-blog.csdnimg.cn/img_convert/4bb027beacaa56e65cffac584f962363.png)
现在我们就可以通过 内存分析工具
看看这个无参构造长什么样子。
回到 InterImpl
实现类,然后找到 Methods
。
因为构造方法也是方法,所以它也会罗列在 Methods
里面。
在实现类 InterImpl
的字节码文件中,它有两个方法,第二个方法 method()
就是我们自己重写的 method()
方法。
除此之外还有一个,那就是第一个,这个就是那个 无参构造
。
此时我们就知道了,如果Java给你添加了 无参构造
,此时在 Methods
里面,我是可以用眼睛看到的。
![image-20240418090623269](https://img-blog.csdnimg.cn/img_convert/cffba5743965f8938478f5866074d9f6.png)
这是我们就可以来看一下在 Inter
接口字节码文件有没有 构造方法
。
可以看到 Inter
接口字节码文件的 Methods
中只有一个我们自己写的 method()
抽象方法,并没有发现有构造方法。
因此通过这个我们就能清晰的知道,在接口中,是没有构造方法的。
三、成员方法
1)概念
在JDK以前:接口中只能定义抽象方法。默认使用 public abstract
修饰的,就算你没写,Java也会帮你加上。
但是到了JDK和JDK9的时候,Java进行了更新,就可以写有方法体的方法了。
JDK8的新特性:接口中可以定义有方法体的方法
JDK9的新特性:接口中可以定义私有方法。
这两个到后面我们会单独再说,因此我们现在暂时还认为接口中只能写抽象方法即可。
2)通过 内存分析工具
证明
紧接构造方法的证明,可以看见,我们在接口中写的抽象方法,Java也会默认帮你加上 public abstract
修饰词。
四、总结
1、成员变量只能是常量,默认是用 public static final
修饰的。
2、在接口当中是没有构造方法的。
3、在JDK7以前,接口中的成员方法只能是抽象方法,这个方法的前面默认用 public abstract
修饰。
PS:虽然 成员变量
和 成员方法
的修饰符你不写,Java也会帮你加上,但是由于我们现在是属于初学者,这些东西我们暂时先不要省略。等以后牛逼了,那个时候就可以省略了。