《Java从入门到精通》第九章学习笔记
第9章 类的高级特性
一、抽象类
抽象类只声明方法的存在,不能被实例化,就是说抽象类不能创建其对象,在定义抽象类时要在class前面加上abstract关键字。
1 /*定义一个抽象类Fruit,并定义其抽象方法 2 *在其子类中实现该抽象方法 3 */ 4 abstract class Fruit { 5 public String color; 6 public Fruit(){ 7 color="green"; 8 } 9 //定义一个抽象方法 10 public abstract void harvest(); 11 } 12 13 public class Farm { 14 public static class Apple extends Fruit{ 15 @Override 16 public void harvest(){ 17 System.out.println("收获苹果!"); 18 } 19 } 20 21 public static void main(String[] args){ 22 Apple apple=new Apple(); 23 System.out.println(apple.color); 24 apple.harvest(); 25 } 26 }
二、内部类
在一个类中再定义一个类,即内部的成为内部类。内部类可以直接存取外部类的私有成员变量。
1、成员内部类:
1 public class OuterClass { 2 innerClass in=new innerClass();//外部类中实例化内部类 3 public void ouf(){ //外部类方法中通过内部类实例对象调用内部类方法 4 in.inf(); 5 } 6 class innerClass{ //定义内部类 7 innerClass(){ //内部类构造方法 8 } 9 public void inf(){ //内部类成员方法 10 } 11 int y=20; //定义内部类成员变量 12 } 13 public innerClass doit(){ //定义外部类方法,返回类型为内部类引用类型 14 //y=4; //外部类方法中不能直接访问内部类成员变量 15 System.out.println("mark0:doit方法中的输出"+in.y); 16 in.y=4; //必须通过内部类实例对象访问 17 return new innerClass(); 18 } 19 public static void main(String[] args){ 20 OuterClass out=new OuterClass(); 21 OuterClass out1=new OuterClass(); 22 OuterClass.innerClass in=out.doit(); 23 //通过doit方法实例化内部类对象in 24 //内部类的对象实例化操作必须在外部类或外部类的非静态方法中实现 25 System.out.println("mark1:out.in方法中的输出"+out.in.y); 26 System.out.println("mark2:直接in的输出--??这里输出为什么是20??"+in.y);//这里输出为什么是20?? 27 28 OuterClass.innerClass ina=out1.new innerClass(); 29 //或者通过外部类的实例对象调用内部类的构造方法 30 System.out.println("mark3:out1.in方法中的输出"+out1.in.y); 31 System.out.println("mark4:直接ina的输出"+ina.y); 32 } 33 }
*如果外部类中和内部类中定义了同名称的成员变量,可以通过this关键字指定。
1 public class TheSameName { 2 private int x; 3 private class Inner{ 4 private int x=9; 5 public void doit(int x){ 6 x++; //调用方法的形参x 7 this.x++; //调用内部类的变量x 8 TheSameName.this.x++; //调用外部类的变量x 9 } 10 } 11 }
2、局部内部类
局部内部类即是在类的方法中定义的内部类。相应地,局部内部类的作用范围也是在这个方法体内。
1 public class SellOutClass { 2 private String name; //定义成员变量 3 public SellOutClass(){ //定义构造函数 4 name="苹果"; 5 } 6 public void sell(int price){ //定义成员方法 7 class Apple{ //定义局部内部类 8 int innerPrice=0; //局部内部类的成员变量 9 public Apple(int price){ //局部内部类的构造方法 10 innerPrice=price; 11 } 12 public void price(){ //局部内部类的成员方法 13 System.out.println("现在开始销售"+name); 14 System.out.println("单价为:"+innerPrice+"元"); 15 } 16 } 17 Apple apple=new Apple(price);//实例化局部内部类 18 apple.price(); //调用局部内部类的方法 19 } 20 public static void main(String[] args){ 21 SellOutClass sample=new SellOutClass();//创建实例化对象 22 sample.sell(100); //通过该对象调用SellOutClass的方法 23 } 24 25 }
3、匿名内部类
有时候内部类根据情况可以不取名,而直接通过创建的类的实例对象去实现,即在实例对象的体内编写代码。
因为匿名内部类没有名称,所以其使用默认的构造方法来生成内部类的对象。并且在匿名内部类定义结束后需要加分号。
1 public class OutString { 2 3 public static void main(String[] args) { 4 final String sourceStr="Ji Lin Province !"; 5 IStringDeal s=new IStringDeal(){ //编写匿名内部类 6 @Override //重写接口的方法 7 public String filterBlankChar(){ 8 String convertStr=sourceStr; 9 convertStr=convertStr.replaceAll(" ",""); 10 return convertStr; 11 } 12 }; //注意这里要加分号 13 System.out.println("源字符串:"+sourceStr); 14 System.out.println("转换后的字符串:"+s.filterBlankChar()); 15 } 16 }
1 //定义接口 2 public interface IStringDeal { 3 public String filterBlankChar(); 4 }
4、静态内部类
静态内部类中可以定义静态成员(非静态内部类则不可以);同时静态内部类不可以使用外部类的非静态成员。
5、内部类的继承
与普通类一样,内部类也可以被继承。在某个类继承内部类时,必须强制给这个类一个带参构造方法,并且该构造方法的参数
必须是内部类的外部类的引用。
class A{ class B{ } }//创建A的内部类B public class OutputInnerClass extends A.B{ public OutputInnerClass(A a){ a.super(); } }
三、class类与Java反射
通过Java反射机制可以在程序中访问已经装载到JVM中的对象的描述,实现访问、检测和修改描述Java对象本身信息的功能。在java.lang.reflect包中提供了对该功能的支持。
所有Java类都继承了Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。代码如下:
Class textFieldC=JTextField.getClass(); //textField为JTextField类的对象
通过这个对象textFieldC,可以访问用来返回该对象的textField对象的描述信息,主要包括以下内容:
*包路径:getPackage();
*类名称:getName();
*继承类:getSuperclass(); //获得该类继承的类
*实现接口:getInterfaces(); //获得该类实现的所有接口
*构造方法:getConstructors();//获得所有权限为public的构造方法
*方法:getMethods(); //获得所有权限为public的方法
*成员变量:getFields() //获得所有权限为public的成员变量
*内部类:getClasses()
四、实战练习
1 /*编写Java程序,创建一个类,并在其中创建成员内部类,通过该内部类计算 2 *从1到任意数的和的操作 3 *在外部类中进行测试 4 */ 5 import java.util.Scanner; 6 public class Sum { 7 InnerSum inner=new InnerSum(); 8 public class InnerSum{ 9 public int getSum(int n){ 10 if(n==1){ 11 return 1; 12 }else { 13 return getSum(n-1)+n; 14 } 15 } 16 } 17 public static void main(String[] args){ 18 Scanner scan=new Scanner(System.in); 19 System.out.println("请输入一个正整数:"); 20 int x=scan.nextInt(); 21 Sum sum=new Sum(); 22 int xSum=sum.inner.getSum(x); 23 System.out.println("从1到"+x+"之和为"+xSum); 24 } 25 }
//定义接口 public interface MyString { String makeString(); } import java.util.Scanner; public class Demo { //创建一个接口作为参数的成员方法 public void showMyString(MyString a){ String x=a.makeString(); System.out.println("my string is:"+x); } public static void main(String[] args) { // TODO Auto-generated method stub Demo myDemo=new Demo();//实例化对象 //调用成员方法 //方法一:实参通过匿名内部类的方法创建 myDemo.showMyString(new MyString(){ public String makeString(){ System.out.println("plz input your string:"); Scanner scan=new Scanner(System.in); return scan.nextLine(); } }); //方法二:先通过匿名内部类创建接口的实例 MyString myStr1=new MyString(){ public String makeString(){ System.out.println("plz input your string:"); Scanner scan=new Scanner(System.in); return scan.nextLine(); } }; //再把上述创建的接口实例作为参数传递 myDemo.showMyString(myStr1); } }