2018.4.22
内部类
成员内部类
人:
成员变量:
体重,性别,血液
成员方法:
睡觉,吃饭,跑步,敲代码
心脏:
心跳行为
会使用到人体内的成员变量,血液。
心室和心房
[特征]
在人类中,有些东西,比如内脏用成员方法或者成员变量描述都闲着有点不太合适,因为这些内脏是属于[人类的一部分],而且会使用人体的一些属性
但是又拥有自己的一些【特征】
[思考]
能不能把这些器官认为是一个类,一个属于人类内部的一个类
内部类:
1.成员内部类
2.局部内部类
3.匿名内部类
内部类和外部类关系:
1.成员内部类可以使用外部类的成员变量和成员方法,不管用什么权限修饰public private,都可以使用 ,因为这是在内部类的内部使用。
2.【在外部类的外部创建外部类的内部类对象】
格式如下:
外部类名.内部类名 内部类对象名 = new 外部类().new 内部类名();
例如:
Outer.inner inner = new Outer().new Inner();//第一个new是java虚拟机用的,第二个new是Outer用的
【第一个知识点】:普通的成员变量和成员方法,在没有对象的情况下,不能在类外使用
3.如果内部类和外部类存在同名的成员变量,这里默认是就近原则,使用的是内部类的成员变量,如果想要使用外部类的成员的:
格式:
外部类名.this.同名变量;
外部类名.this.同名成员方法(参数列表);
4.在外部类的类内方法中,可以创建内部类的对象。
class Outer {
int num = 100;//外部类的成员变量
private static int s = 10;
public void test() {
System.out.println("外部类的test方法");
}
public void testOuter() {
System.out.println("外部类的成员方法");
}
class Inner {//这是Outer类的一个成员内部类
int i = 10;//成员内部类的成员变量
int num = 50;
public void testInner() {
System.out.println("内部类的成员方法");
//如何调用重名的成员变量。
System.out.println("内部类成员变量:"+num);//请问打印的是50/100(就近原则)
System.out.println("外部类成员变量:"+Outer.this.num);
//如何调用重名的成员方法
//调用自己内部类的成员方法
test();
//调用外部类的成员方法
Outer.this.test();
//内部类调用外部类静态私有话成员变量
System.out.println(s);
//调用外部类的静态成员方法
testStatic();
}
public void test() {
System.out.println("内部类的test方法");
}
}
//new Inner().test(); 内部类对象不能在外部类内直接调用方法。
//但是内部类对象可以在外部类的方法中创建,并且在方法中调用内部类方法
//在【外部类】中定义【内部类的类对象】,来完成外部类无法做到的事。
public void createInnerClass() {
//外部类的成员方中调用内部类的构造方法,通过new关键字来创建内部类类对象使用
Inner inner = new Inner();
inner.testInner();
}
public static void testStatic () {
System.out.println("外部类的静态成员方法");
}
}
public class Demo1 {
public static void main(String[] args) {
Outer outer = new Outer();
//outer.createInnerClass();
//想要在这里创一个Inner类对象
//Entry<K,V> entrySet
//Set<Map.Entry<K,V>>
//数据类型是Outer.Inner 表示是外部类里面的内部数据类型
//没有外部类的对象就不能调用成员方法,成员变量或者成员内部类。
//如果创建成员内部类的类对象。
Outer.Inner inner = new Outer().new Inner();
//inner.testOuter();在类外内部类对象不能调用外部类方法
//outer.testInner();在类外外部类对象不能调用内部类的成员方法
inner.testInner();//在类外内部类对象可以直接调用内部类的方法。
outer.testOuter();//在类外外部类对象可以直接调用外部类方法
}
}
结果:
内部类的成员方法
内部类成员变量:50
外部类成员变量:100
内部类的test方法
外部类的test方法
10
外部类的静态成员方法
外部类的成员方法
局部内部类
局部内部类:放在方法或者函数内的类,称之为局部内部类
【第二个知识点】
1.局部变量
【生存期】
从声明定义位置开始,到代码块结束
【作用域】
只能在当前代码块内部。
2.类对象的
【生存期】
通过new关键字创建的时候开始,JVM垃圾回收机制调用时,销毁该对象,结束。
【作用域】
哪个引用变量拥有这个对象首地址,哪里就是他的作用域。
说明:
局部内部类只能函数或者方法中使用,方法或者函数外不能使用。
发现:
局部内部类中,貌似不能【修改】所在方法或者函数中的局部变量
原因:以下内容可以理解。
------------------------------------------------------------------
局部内部类的对象是在函数或者方法的内部通过JVM借助于New关键字,和局部内部类的狗方法,创建
的一个类对象,并且该对象是由JVM的回收机制回收的。
但是局部变量n是在testInner()方法中,而这个局部变量n的生存周期是和testInner()该方法的大括号有关,
生存期和作用域都是在大括号以内。
如果在testInnner的方法内部,MethodInner这个类是方法中的局部内部类,而创建的对象在使用testInner()方法中的局部变量时,
因为对象的销毁时间不确定,但是一定是晚于局部变量的销毁的,
这里隐含了一个类对象【延迟局部变量中生存周期】的,这个是不符合Java原理的。
这就是为什么不能修改,因为有可能在这个对象吧诶使用的时候,局部变量的内存空间已经被内存收回,
换而言之这个局部变量不存在了!!
为了解决这个问题
【解决方式】
如果是在局部内部类中使用了苏在函数或者方法的局部变量,该变量用final修饰
---------------------------------------------------------------------
要求
【第三个知识点】
如果是局部内部类要使用函数或者方法的局部变量,该变量用【final】修饰。
class Test {
int num = 100;
public void testInner() {
//这里是在方法中定义一个类,这个类只能在当前方法或者函数中使用。
int n = 10;
class MethodInner {
int i = 10;//成员变量在类内任何地方都可以使用。
public void function() {
num = 20;
//n = 20;
System.out.println(i);
System.out.println(num);
System.out.println("局部内部类的成员方法");
}
}
MethodInner inner = new MethodInner();
inner.function();
}
}
public class Demo2 {
public static void main(String[] args) {
// for (int i = 0; i < 10; i++) {
// System.out.println(i);
// }
//System.out.println(i);
new Test().testInner();
}
}
结果:
10
20
局部内部类的成员方法
匿名内部类
【第四个知识点】
类的本体
在类声明部分,大括号里面的内容就是类的本体~~
class Test {
//成员变量
//成员方法
}
匿名内部类就是没有名字的类,但是有类的本体!!!!
【第五个知识点】
看到内部类要认识
哦,这个就是内部类。
//抽象类,所有继承抽象类的子类都必须实现抽象类的方法。
abstract class Animal {
int age;
public abstract void test();
abstract public void jump();
}
class CodingMonkey extends Animal {//会报错 必须实现上面两个方法。
//以下两个方法是类的本体!!
@Override
public void test() {
System.out.println("这是类本题中的一个成员方法");
}
@Override
public void jump() {
System.out.println("大吉大利,今晚吃鸡。");
}
}
interface A {
int i = 0;//默认缺省属性 顺丰 public static final
public void testA();//缺省abstract, 没有方法体
}
public class Demo3 {
public static void main(String[] args) {
CodingMonkey monkey = new CodingMonkey();
Animal a = new CodingMonkey();//多态,父类的引用指向子类的对象。
a.test();
monkey.test();
monkey.jump();
//抽象类有没有自己的类对象!? 不能
//原因:抽象类里面有抽象方法, 抽象方法没有方法体,假如有自己类对象调用抽象方法如何运行?所以悖论。
//创建了一个匿名内部类的对象赋值给了animal
/*
Animal是一个抽象类,animal是抽象类的一个引用类型变量
new Animal() {
发现这里面的内容和继承该抽象类的子类内容一致,都是抽象类,要求子类实现的方法
这里是类的本体
而这里可以看做是一个类,但是这个类没有名字
所以:这个就是【匿名内部类】
这里创建了一个【匿名内部类】的对象,赋值给了Animal的引用数据类型 animal
这里隐含了一个【继承】关系。
};
*/
new Animal() {
@Override
public void test() {
System.out.println("这是匿名内部类里面的test方法");
}
@Override
public void jump() {
System.out.println("匿名内部类里面的jump方法");
}
}
.jump();
//匿名内部类的匿名对象直接调用方法,用于接口。
new A() {
//这里是一个类【遵从】接口之后要求实现接口中的抽象方法,这里也是一个【匿名内部类】,是类的本体。
@Override
public void testA() {
System.out.println("匿名内部类实现interface A中的testA()方法");
}
}
.testA();
//用于java android开发
Integer[] arr = {3,2,4,5,6,1};
//匿名内部类的匿名对象作为方法的参数。
Arrays.sort(arr,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
} );
System.out.println(Arrays.toString(arr));
}
}