内部类是一个定义在另一个类中的类。那为什么要使用内部类呢?其主要原因有以下三点:
- 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据
- 内部类可以对统一包中的其他数据隐藏起来,增强面向对象的封装性
- 当定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷
通过代码来理解一下:
先创建人Person这样一个类,看一下如何在类中创建内部类
public class Person {
//对象属性
private String[] sex = {"男","女"};//定义一个私有的sex数组赋值
//创建内部类, 内部类最本质的语法就是在一个类中创建另一个类。类是可以嵌套的。
class XiaoMing {
}
}
也可以在前面加上public,公共类,也可以不加,是一个默认的类。
public class Person {
//对象属性
private String[] sex = {"男","女"};//定义一个私有的sex数组赋值
public class XiaoMing {
}
}
加和不加public的区别?
加上public的类叫公共类,也叫主类。不加public就叫普通的类。
不加public也不报错,但是是一个普通的类。文件,在里面可以创建无数个类。向下面这样的写法这样的写法相当于写了三个文件,分别是Person.java,XiaoMing.java, Xh.java。
class Person {
//对象属性
private String[] sex = {"男","女"};//定义一个私有的sex数组赋值
}
class XiaoMing {
}
class Xh {
}
可以写三个文件,也可以把他们合到一个文件里面写多个类。如果这里面没有公共类可以,但是能加public的公共类只能有一个,且文件名称必须要和主类的文件名称相同。
所以只能Person为主类。
再建一个test.java,去使用那个类,
public class test {
public static void main(String[] args) {
new Person();//在堆中开辟一个空间
}
}
堆中开辟的空间变量如果没有在栈中去指向的话,java里面有个jvm,垃圾处理机制虚拟机会把没有用的会回收掉。但是要证明主类跟普通类区别的时候可以补全,可以说明这个类能够用到
public class test {
public static void main(String[] args) {
Person person = new Person();//在堆中开辟一个空间
}
}
再一个类(可以补全),也可以用
public class test {
public static void main(String[] args) {
Person person = new Person();//在堆中开辟一个空间
new XiaoMing();
}
}
在其他包里的类的主方法里 new Person();不同包的需要引入:import .....
也可以用,当new XiaoMing();时有错误,主动引入导入 会出现 is not visible;不可见,所以区别有了,公共类可以在任何其他的类中使用,普通类只能在同包内使用, 范围更小。语法不在于好坏,在于它的价值是多少。
高内聚低耦合
需要main方法的时候,可以在下面写一个类。
内部类可以加public,也可以不加。相当于一个块里面又一个块,内部类里可以加多加public。
public class Person {
public static void main(String[] args) {
Person person = new Person();//在堆中开辟一个空间
public class XiaoMing(){
}
public class XiaoMing1(){
}
}
}
public class Person {
public static void main(String[] args) {
private String[] sex = {"男","女"};
//创建内部类
class XiaoMing(){
private String Xiaoming_sex;//全局变量,只要不在函数体内的变量都叫全局变量
private String showSex() {//前面用哪种都可以 private、public、protected、还有什么都不写。
xiaoming_sex = "Xh";
return "xiaoming_sex";
}
}
}
看看内部域能不能访问外部域所有访问权限修饰符定义的变量的值,
public class Person {
public static void main(String[] args) {
private String[] sex = {"男","女"};
//创建内部类
class XiaoMing(){
private String Xiaoming_sex;
private String showSex() {
xiaoming_sex = sex[0];
return "xiaoming_sex";
}
}
}
怎么访问内部类?
public class Person {
public static void main(String[] args) {
private String[] sex = {"男","女"};
//创建内部类
class XiaoMing(){
private String Xiaoming_sex;
private String showSex() {
xiaoming_sex = sex[0];
return "xiaoming_sex";
}
}
//创建对象方法,最好是公共的
public void show_xiaoming_sex{
XiaoMing xiaoMing = new XiaoMing();
System.out.println(xiaoMing.showSex());
}
}
相当于内部类就是一个变量,在这个外部不可以new的 但是在方法里面可以,咱们要把小明性别是男给返回出来,打印一下调用完的方法,这就是基本的语法。把内部类new了一个对象,调用内部类对象方法然后会有一个产物打印出来。就可以看到男输出。
public class test {
public static void main(String[] args) {
Person person = new Person();
person.show_xiaoming_sex();//调用一下这个方法
}
}
我们本来可以把内部类的数据放到外面private下面,虽然private已经很安全了,以为只能是本类下访问,但是我们再包一层的话,只能在内部类外部new,去访问,更安全一些。就是在类中再套一个类,一个类就是一个防火墙,两个就是两个防火墙,所以更安全,增强封装性。
哪个类都可以写main方法,也可以不写,可以提出去,在里面进行创建,在test里进行调用,也可以合到一起。在下面建一个公共类,
public static void main(String[] args) {
Person person = new Person();
person.show_XiaoMing_sex();
}
内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。这一点能够做到,为了能够运行程序,内部类的对象总有一个隐式引用,他指向了创建他的外部类对象
Xiaoming是一个内部类,里面有一个outer,里面包含了隐式引用一直指向person对象,所以里面的sex,等其他属性都可以访问到。
outer不是java关键字,我们只是用它说明内部类中的机制
重点:借助于内部类可以实现类似于多继承的作用。
再创建一个叫ZhangSan的类,并在张三这个类里再建一个ZuoJia的类,
public class ZhangSan extends ZuoJia {
//创建两个内部类,用类extends继承作家、画家,已经具有了父类的两个方法
class HuaJiaA extends HuaJia{
}
class ZuoJiaA extends ZuoJia{
}
public void xie() {
ZuoJiaA zuoJiaA = new ZuoJiaA();//得到内部类的对象
zuoJiaA.xie();
}
public void hua() {
HuaJiaA huaJianA = new HuaJiaA();
HuaJiaA.hua();
}
public static void main() {//调用zhangSan对象
ZhangSan zhangSan = new ZhangSan();
zhangSan.xie();//调写的方法
zhangSan.hua();
}
}
class ZuoJia {//作家——写
public void xie() {
System.out.println("写作");
}
}
class HuaJia{//画家——画
public static void hua() {
System.out.println("画画");
}
}
内部类的几种表现形式
一、非静态成员式内部类
定义:成员式内部类如同外部类的一个普通方法
成员式内部类有以下特性:
- 持有父类引用,故可以访问父类任何访问权限的变量、方法
- 非静态内部类中不能声明static成员
在对象方法中可以使用类属性。
public class ZhangSan extends ZuoJia {
static String sex = "男";//类属性,在对象方法中可以使用类属性。
//创建两个内部类,用类extends继承作家、画家,已经具有了父类的两个方法
class HuaJiaA extends HuaJia{
}
class ZuoJiaA extends ZuoJia{
}
public void xie() {
System.out.println("sex");//打印一下写 男
ZuoJiaA zuoJiaA = new ZuoJiaA();//得到内部类的对象
zuoJiaA.xie();
}
public void hua() {
HuaJiaA huaJianA = new HuaJiaA();
HuaJiaA.hua();
}
public static void main() {//调用zhangSan对象
ZhangSan zhangSan = new ZhangSan();
zhangSan.xie();//调写的方法
zhangSan.hua();
}
}
class ZuoJia {//作家——写
public void xie() {
System.out.println("写作");
}
}
class HuaJia{//画家——画
public static void hua() {
System.out.println("画画");
}
}
然后把属性定义为对象属性,方法为static ,反过来访问不到
public class ZhangSan extends ZuoJia {
String sex = "男";//对象属性
public static void xie() {//静态方法
System.out.println("sex");
}
public static void main() {//调用zhangSan对象
}
}
对象方法中可以使用静态变量,而静态方法中不能使用对象变量(属性)。再一个普通的属性objattr
对象方法可以使用对象属性,也可以使用类属性,而类方法只能只能类属性;
静态方法中可以使用静态属性,也可以使用非静态属性。
public class ZhangSan extends ZuoJia {
oublic static String classAttr = "静态属性(类属性)";//对象属性
public String objAttr = "对象属性";
//非静态方法(对象方法)
public void objFun() {
System.out.println(classAttr);
System.out.println(objAttr);
}
//静态方法(类方法)
public static void classFun() {
System.out.println(classAttr);
}
public static void main() {//调用zhangSan对象
}
}