【JAVA学习笔记】21 内部类

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));
    	
    	
    }
    }

猜你喜欢

转载自blog.csdn.net/u013182992/article/details/80472045