JAVA自学教程之(内部类及其特点)



JAVA自学教程之(内部类及其特点)。内部类:
内部类就是一个类定义在一个类里,定义在类中的类就叫做内部类
一、访问特点:
内部类可以直接访问外部类的成员,包括私有成员 外部类要访问内部类的成员,必须创建内部类的对象

简单体现:

 

  1. import out.in;
  2. class out
  3. {
  4.     private int num  = 3;
  5.     class in
  6.     {
  7. public void showou()
  8.         {
  9.             System.out.println(num);
  10.         }
  11.     }
  12.     public void showin()
  13.     {
  14.         in BLF = new in();
  15.         BLF.showou();
  16.     }
  17. }
  18. public class Main
  19. {
  20.     public static void main(String[] args)
  21.     {
  22.         out BLF = new out();
  23.         BLF.showin();
  24.     }
  25. }
import out.in;

class out
{
	private int num  = 3;
	class in
	{
		public void showou()
		{
			System.out.println(num);
		}
	}
	public void showin()
	{
		in BLF = new in();
		BLF.showou();
	}
}
public class Main
{
	public static void main(String[] args)
	{
		out BLF = new out();
		BLF.showin();
	}
}

二、什么时候用?
一般用于分析事物A时,发现该事物A描述中还有事物B,发现这个事物B还在访问被描述的事物A的内容,那么这个事物B就要定义为内部类
比如:描述身体的时候,还有大脑,而大脑还可以访问人体其他部位,那么大脑就要定义内部类
三、内部类的小特点:
1.内部类可以被修饰符 修饰。
private class in() 2.直接访问外部类中的内部类成员 如果直接 in BLF = new in();,这种方式是不行的,假设我还有个ou2类他的内部类也是in,那这个BLF是谁的? 定义方式: out.in BLF2 = new out().new in();//这种格式不多见,一般内部类都是私有的 BLF2.showou();

3.内部类是静态的,那么内部类就相当于是外部类 因为外部类一加载就存在了

 

 

  1. class out
  2. {
  3.     private static int num  = 3;
  4.     static class in
  5.     {
  6.         public void showou()
  7.         {
  8.             System.out.println(num);//静态类中访问外部类的成员变量也必须是静态的
  9.         }
  10.         public static void showsta()
  11.         {
  12.             System.out.println(“sta show”+num);
  13.         }
  14.     }
  15.     public void showin()
  16.     {
  17.         in BLF = new in();
  18.         BLF.showou();
  19.     }
  20. }
  21. public class Main
  22. {
  23.     public static void main(String[] args)
  24.     {
  25.         //内部类是静态的,成员是非静态的
  26.         out.in BLF = new out.in();
  27.         BLF.showou();
  28.         //如果内部类是静态的,成员也是静态的情况
  29.         out.in.showsta();
  30.     }
  31. }
class out
{
	private static int num  = 3;
	static class in
	{
		public void showou()
		{
			System.out.println(num);//静态类中访问外部类的成员变量也必须是静态的
		}
		public static void showsta()
		{
			System.out.println("sta show"+num);
		}
	}
	public void showin()
	{
		in BLF = new in();
		BLF.showou();
	}
}
public class Main
{
	public static void main(String[] args)
	{
		//内部类是静态的,成员是非静态的
		out.in BLF = new out.in();
		BLF.showou();
		//如果内部类是静态的,成员也是静态的情况
		out.in.showsta();
	}
}

PS:如果内部类中有定义了静态成员,那么该内部类也必须是静态的,否则编译失败
四、内部类细节:
为什么内部类可以直接访问外部类中的成员呢? 因为内部类持有外部类的引用,外部类名.this

 

 

  1. class out
  2. {
  3.      int num  = 3;
  4.     class in
  5.     {
  6.         int num = 4;
  7.         public void showou()
  8.         {
  9.             int num = 5;
  10.             System.out.println(num);//如果想打印4,this.num
  11.             System.out.println(this.num);
  12.             //也可以
  13.             System.out.println(in.this.num);
  14.             //如果想打印3
  15.             System.out.println(out.this.num);
  16.         }
  17.     }
  18.     public void showin()
  19.     {
  20.         in BLF = new in();
  21.         BLF.showou();
  22.     }
  23. }
  24. public class Main
  25. {
  26.     public static void main(String[] args)
  27.     {
  28.         out.in BLF = new out().new in();
  29.         BLF.showou();
  30.     }
  31. }
class out
{
	 int num  = 3;
	class in
	{
		int num = 4;
		public void showou()
		{
			int num = 5;
			System.out.println(num);//如果想打印4,this.num
			System.out.println(this.num);
			//也可以
			System.out.println(in.this.num);
			//如果想打印3
			System.out.println(out.this.num);
		}

	}
	public void showin()
	{
		in BLF = new in();
		BLF.showou();
	}
}
public class Main
{
	public static void main(String[] args)
	{
		out.in BLF = new out().new in();
		BLF.showou();
	}
}

PS:实际开发不出现这种写法
五、内部类的局部类
内部类除了可以存放在成员上,也可以存放在局部位置上

 

 

  1. class out
  2. {
  3.     int num = 3;
  4.     void show1()
  5.     {
  6.         class in
  7.         {
  8.             void show()
  9.             {
  10.                 System.out.print(num);
  11.             }
  12.         }
  13.         in blf = new in();//创建对象,但是不能在外部类中创建
  14.         blf.show();
  15.     }
  16. }
  17. public class Main
  18. {
  19.     public static void main(String[] args)
  20.     {
  21.         out blfOut = new out();
  22.         blfOut.show1();
  23.     }
  24. }
class out
{
	int num = 3;
	void show1()
	{
		class in
		{
			void show()
			{
				System.out.print(num);
			}
		}

		in blf = new in();//创建对象,但是不能在外部类中创建
		blf.show();
	}

}
public class Main
{
	public static void main(String[] args)
	{
		out blfOut = new out();
		blfOut.show1();
	}
}


特例:
1.从内部中访问局部变量,需要被声明为最终类型 也就是说,内部类在局部位置上只能访问局部中被final修饰的局部变量

 

 

  1. class out
  2. {
  3.     int num = 3;
  4.     void show1()
  5.     {
  6.         final int x = 5;
  7.         class in
  8.         {
  9.             void show()
  10.             {
  11.                 System.out.println(x);
  12.             }
  13.         }
  14.         in blf = new in();
  15.         blf.show();
  16.     }
  17. }
  18. public class Main
  19. {
  20.     public static void main(String[] args)
  21.     {
  22.         out blfOut = new out();
  23.         blfOut.show1();
  24.     }
  25. }
class out
{
	int num = 3;
	void show1()
	{
		final int x = 5;
		class in
		{
			void show()
			{
				System.out.println(x);
			}
		}

		in blf = new in();
		blf.show();

	}
}
public class Main
{
	public static void main(String[] args)
	{
		out blfOut = new out();
		blfOut.show1();

	}
}

为什么要定义为final?
详见下面代码
我们知道所有的类都是继承Object类的

 

 

 

  1. class out
  2. {
  3.     int num = 3;
  4.     Object show1()//如果这个方法是一个返回对象的方法
  5.     {
  6.          int x = 5;
  7.         class in
  8.         {
  9.             void show()
  10.             {
  11.                 System.out.println(x);
  12.             }
  13.         }
  14.         Object blf = new in();
  15.         //blf.show();
  16.         return blf;
  17.     }
  18. }
  19. public class Main
  20. {
  21.     public static void main(String[] args)
  22.     {
  23.         out blfOut = new out();
  24.         Object blfObject = blfOut.show1();//blfObject接受这个对象,那么blfOut的show1方法就执行完了
  25.                  //那么就意味着show1的x就没了,所以必须加final,final修饰的x是终身为5,不会变化的
  26.     }
  27. }
class out
{
	int num = 3;
	Object show1()//如果这个方法是一个返回对象的方法
	{
		 int x = 5;
		class in
		{
			void show()
			{
				System.out.println(x);
			}
		}

		Object blf = new in();
		//blf.show();
		return blf;
	}
}
public class Main
{
	public static void main(String[] args)
	{
		out blfOut = new out();
		Object blfObject = blfOut.show1();//blfObject接受这个对象,那么blfOut的show1方法就执行完了
                 //那么就意味着show1的x就没了,所以必须加final,final修饰的x是终身为5,不会变化的

	}
}

六、匿名内部类
就是内部类的简写形式
前提:内部类必须继承或实现一个外部类或者接口
内名内部类,其实就是一个匿名子类对象
格式:new 父类or接口()(子类内容)

  1. import org.ietf.jgss.Oid;
  2. abstract class demo
  3. {
  4.     abstract void show();
  5. }
  6. class out
  7. {
  8.     int num = 3;
  9.       /* //有名字
  10.         class in extends demo
  11.         {
  12.             void show()
  13.             {
  14.                 System.out.println(num);
  15.             }
  16.         }
  17.         public void set()
  18.     {
  19.         new in().show();
  20.     }*/
  21.     //没名字:匿名内部类
  22.     public void set()
  23.     {
  24.         new demo() //对象
  25.         {
  26.             void show()
  27.             {
  28.                 System.out.println(num);
  29.             }
  30.             void  haha()
  31.             {
  32.             }
  33.         }.show();//对象.show()
  34.     }
  35. }
  36. public class Main
  37. {
  38.     public static void main(String[] args)
  39.     {
  40.         out blfOut = new out();
  41.         blfOut.set();
  42.     }
  43. }
import org.ietf.jgss.Oid;

abstract class demo
{
	abstract void show();
}

class out
{
	int num = 3;
	  /* //有名字
		class in extends demo
		{
			void show()
			{
				System.out.println(num);
			}
		}
		public void set()
	{
		new in().show();
	}*/
	//没名字:匿名内部类
	public void set()
	{
		new demo() //对象
		{
			void show()
			{
				System.out.println(num);
			}
			void  haha()
			{

			}
		}.show();//对象.show()

	}

}
public class Main
{
	public static void main(String[] args)
	{
		out blfOut = new out();
		blfOut.set();

	}
}

匿名内部类的应用:

 

  1. import org.ietf.jgss.Oid;
  2. import org.w3c.dom.DOMError;
  3. interface  demo
  4. {
  5.      void show1();
  6.      void show2();
  7. }
  8. class out
  9. {
  10.     public void set()
  11.     {//当有多个方法时,就不用上述方法调用了
  12.         //匿名内部类没有名字,但是可以给父类起一个名字
  13.         demo blfDemo = new demo()
  14.         {
  15.             public void show1()
  16.             {
  17.                 System.out.println(“show1″);
  18.             }
  19.             public void show2()
  20.             {
  21.                 System.out.println(“show2″);
  22.             }
  23.             public void haha()
  24.             {
  25.                 System.out.println(“haha”);
  26.             }
  27.         };
  28.         blfDemo.show1();
  29.         blfDemo.show2();
  30.         blfDemo.haha();//编译失败,编译看左边,接口里只有两个方法,没有haha方法
  31.     }
  32. }
  33. public class Main
  34. {
  35.     public static void main(String[] args)
  36.     {
  37.         new out().set();
  38.     }
  39. }
import org.ietf.jgss.Oid;
import org.w3c.dom.DOMError;

interface  demo
{
	 void show1();
	 void show2();
}

class out
{
	public void set()
	{//当有多个方法时,就不用上述方法调用了
		//匿名内部类没有名字,但是可以给父类起一个名字
		demo blfDemo = new demo() 
		{
			public void show1()
			{
				System.out.println("show1");
			}
			public void show2()
			{
				System.out.println("show2");
			}
			public void haha()
			{
				System.out.println("haha");
			}

		};
		blfDemo.show1();
		blfDemo.show2();
		blfDemo.haha();//编译失败,编译看左边,接口里只有两个方法,没有haha方法
	}

}
public class Main
{
	public static void main(String[] args)
	{
		new out().set();
	}
}

通常使用的场景之一: 当函数参数是接口类型时,而且接口中的方法不超过三个 可以用匿名内部类作为实际参数进行传递

 

  1. import org.ietf.jgss.Oid;
  2. import org.w3c.dom.DOMError;
  3. interface  demo
  4. {
  5.      void show1();
  6.      void show2();
  7. }
  8. public class Main
  9. {
  10.     public static void main(String[] args)
  11.     {
  12.         //show方法传一个 匿名内部类的匿名对象参数
  13.         //show(new demo(){….});
  14.         //但是一个接口方法一旦超过三个,就失去了阅读性了
  15.         //show(),括号里是一个匿名内部类和他的方法体
  16.         show(new demo()
  17.         {
  18.             public void show1()
  19.             {
  20.                 System.out.println(“show11″);
  21.             }
  22.             public void show2()
  23.             {
  24.                 System.out.println(“show22″);
  25.             }
  26.         });
  27.     }
  28.     public static void show(demo c)
  29.     {
  30.         c.show1();
  31.         c.show2();
  32.     }
  33. }