JAVA学习之笔记(面向对象篇)
面向对象(上)
1、对于构造函数,如果声明为public void structor(),则如果声明该对象时不会调用该构造函数,如果声明为public structor(),则对象会自动调用该构造函数
2、this的使用情况:在还没声明该对象却要调用该对象时,其传递参数可用this;另外在构造函数中其传递的参数跟该类的成员变量相同时,为增加可读性和区别成员变量可用this;
如果一个class有多个构造函数,其中在某个构造函数中需要调用另一个或几个构造函数时可用诸如this()的形式来调用该类的构造函数,其中()中的内容可根据具体的参数调用相应的构造函数
3、垃圾回收,java中也有C++中析构函数的机制,其函数为public void finalize(),当对象被使用完毕需要通过System.gc(),让编译器启动垃圾回收器
4、静态成员变量的访问方式有3种,通过类名访问;通过对象名访问;同一类中的成员函数也可以直接对该静态变量进行访问
5、静态方法的访问跟静态变量的访问类似:通过类名访问;通过对象名访问;对象中的成员函数访问。
6、内部类:在类中直接定义的类,内部类可访问其外部类中的成员变量,反之外部类不能访问内部类中的成员。声明为内部类的好处:代码紧凑,程序更具模块行
面向对象(下)
1、类的继承
2、子类对象的实例化过程
3、finally关键字
4、抽象类
5、接口
//静态成员变量实例
//静态方法
//1、在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。这是因为,对于非静态的方法和变量,需要先创建类的实例对象后才可使用,而静态方法在使用前不用创建任何对象。
//2、静态方法不能以任何方式引用this和super关键字。与1的道理一样,因为静态方法在使用前不用创建任何实例对象,当静态方法被调用时,thsi所引用的对象根本就没产生。
//3、main()方法是静态的,因此JVM在执行main方法时不创建main方法所在的类的实例对象,而已在main()方法中,我们不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。
class Chinese
{
//static Chinese objRsf = new Chinese(); //看看与下面一句二者的区别
Chinese objRsf = new Chinese(); //在该类的内部创建一个对象,以防止其它类创建该类的对象,前提是该类的构造函数为private,如果外面要访问该对象,则需要定义一个供外部访问的方法,且该方法又必须为静态的,因为外部访问它时还没有被创建
//private int count=0; private static int count=0; //统计一共创建了多少个实例对象,实验:如果将static去掉,则结果始终是1 static String country="中国"; //若定义为 private static Stringcountry="中国"; 则在其它类不能进行访问 static //静态代码块:在装载时只被执行一次 { count=2; System.out.println("Static Code!"); } String name; intage;
public static Chinses getInstance() //声明一个可供外部访问的静态方法,好处是无论外部怎样访问都只生成一个对象实例,该方法产生了另一个问题,因为是静态的,不能访问其非静态的方法,即不能访问Chinese(),所以需要声明为:static Chinese objRsf = new Chinese();
{ return objRsf; //返回一个对象 } public Chinese() { //count++; System.out.println(++count); } static void sing() //声明一个静态方法 { System.out.println("啊"); } voidSingOurCountry() { System.out.println(country); sing(); } } class Test Chinese { public static void main(String [] args) { System.out.println(Chinese.country); Chinese ch1 = new Chinese(); ch1.SingOurCountry(); //静态成员变量可以通过类名或对象名来访问,同一类中的成员函数也可以直接对该静态变量进行访问 System.out.println(ch1.Country); Chinese.sing(); //类名访问静态方法 System.out.println("begin");//静态代码块在用到的时候进行加载 newChinese().sing(); //对象访问静态方法 System.out.println("end); newChinese().SingOurCountry();//成员函数访问静态方法 newChinese(); //1 newChinese(); //2 newChinese(); //3 Chinese obj1 = Chinese.getInstance(); //在其它类中访问该对象 Chinese obj2 = Chinese.getInstance(); System.out.println(obj1==obj2); //比较obj1和obj2是不是属于同一个对象,结果是同一对象,但有一个潜在的问题是, //如果在classChinese中声明为ChineseobjRsf = new Chinese();则在多次创建时将被重复创建该对象产生一个循环,直到内存被耗尽 } } //单态设计模式:即在程序中只允许产生一个对象,那样的话,需要把构造函数设为private
6、内部类:在类中直接定义的类,内部类可访问其外部类中的成员变量,反之外部类不能访问内部类中的成员。声明为内部类的好处:代码紧凑,程序更具模块行
//内部类实例:内部类中成功调用外部内中的变量,而外部类不能访问内部类变量
//内部类好处:代码紧凑,程序更具模块性;最大的好处是如果声明为两个类,其中一个类要访问另一个类的成员变量却无能为力
//解决方法是需要在访问类中设置一个访问被访问类的方法Inner
class Outer { intouter_i=100; voidtest() { Inner in=new Inner(); in.display(); } /*static*/ class Inner //加上static关键字后相当于是一外部类,则不能在访问其内部类 { void display() { System.out.println("outer_i-" + outer_i); //内部类中可以访问外部类中的成员变量 } } public static void main(String [] args) { Outer outer = new Outer(); outer.test(); } } //不使用内部类的情况,则需要在访问类中设置一个访问被访问类的方法Inner /*class Outer { intouter_i=100; voidtest() { Inner in=new Inner(this); in.display(); } public static void main(String [] args) { Outer outer = new Outer(); outer.test(); } } class Inner { Outer outer; public Inner(Outer outer) { this.outer=outer; } voiddisplay() { System.out.println("outer_i-" + outer.outer_i); //内部类中可以访问外部类中的成员变量 } } */ //如果函数的局部变量(函数的形参也是局部变量),内部类的成员变量,外部类的成员变量重名,我们应该按下面的程序代码所使用的方式来明确指定我们真正要访问的变量 public class Outer { private int size; public class Inner { private int size; public void doStuff(int size) { size++ ; //引用的是doStuff函数的形参 this.size++; //引用的是Inner类中的成员变量 Outer.this.size ; //引用的是Outer类中的成员变量 } } } //内部类如何被外部类引用 class Outer { private int size=10; public class Inner { public void doStuff() { System.out.println(++size); } } } public class TestInner { public static void main(String [] args) { Outer outer=new Outer(); Outer.Inner inner=outer.new Inner(); inner.doStuff(); } } //方法中定义的内部类嵌套类并非只能在类里定义,也可以在几个程序块的范围之内定义内部类。比如,在方法中,或甚至在for循环体内部,都可以定义嵌套类,例如: //该变量尽管是在一个方法中被定义,但是却不能被访问,因此在方法中定义的内部变量类中能访问方法中的final类型的局部变量,因为用final定义的局部变量相当于是一个常量, //它的生命周期超出了方法运行的生命周期 class Outer { intouter_i=100; voidtest() { /*final*/ int x ; //需要在此加上final后才能在该方法的内部类中访问局部变量x,另外在方法中的该局部变量需要被初始化 class Inner { void display() { System.out.println("outer_i = " + outer_i); System.out.println(x); //去掉final后运行结果会报错 } } Inner in = new Inner(); in.display(); } public static void main(String [] args) { Outer outer=new Outer(); outer.test(); } } 7、java的文档注释 //java的文档注释,java中支持3种形式的注释,其中一种被称为文档注释,它以"/**"开始,"*/"结尾,文档注释提供将程序使用的帮助信息嵌入到程序中的功能, //开发者可以使用javadoc工具将这些信息取出,然后转换成html说明文档,由此可见文档注释提供了编写程序文档的便利方式。 //<br>在html中边换行,@标注会自动换行 import java.io.*; /** *Title: engineer类<br> *Description: 通过engineer类来说明java中的文档注释<br> *Copyright:(c)2003 <br> *Company: XXX公司<br> *@Author: XXX //标记参数,是固定格式 *@Version 1.00 */ public class engineer //注:新建的类为public,其源文件名字也必须是engineer { public String Enginerr_name; /** *这是engineer的构造函数 *@param name engineer的名字 */ public engineer(String name) { } /** *这是repairing方法的说明 *@param sum需要修理的机器总数 *@param alltime需要修理的总时间 *@return Repairing的数量 */ public int repairing(int sum, int alltime) { } } //命令格式:-d directory 默认情况下不生成author和version,所以需要把这两个加进去 //javadoc -d engineer -author -version engineer.java 面向对象(下) 1、类的继承 *通过继承可简化类的定义 *java只支持单继承不允许多重继承 *可以有多层继承,即一个类可以继承某一个类的子类,如B继承了类A,类C又可以继承类B,那么类C也间接继承了类A *子类继承父类所有的成员变量和成员方法,但不继承父类的构造方法。在子类的构造方法中可使用语句super(参数列表)调用父类的构造方法 *如果子类的构造方法中没有显示地调用父类构造方法,也没有使用this关键字调用重载的其它构造方法,则在产生子类的实例对象时,系统默认调用父类无参数的构造方法. 2、子类对象的实例化过程 *分配成员变量的存储空间并进行默认的初始化,就是用new关键字产生对象后,对类中的成员变量按第三章的表3.1中的对应关系对对象中的成员变量进行初始化 *绑定构造方法参数,就是new Person(实际参数列表)中所传递进的参数赋值给构造方法中的形式参数变量 *如有this调用,则调用相应的重载构造方法(被调用重载构造方法又从步骤2开始执行这些流程),按调用的重载构造方法的执行流程结束后,回到当前构造方法,当前构造方法直接跳到步骤6执行 *显式或隐式追溯调用父类的构造方法(一直到Object类为止,Object是所有java类的最顶层父类),父类的构造方法又从步骤2开始对父类执行这些流程,父类的构造方法的执行流程结束后,回到当前构造方法,当前构造方法继续往下执行 *进行实例变量的显式初始化操作,也就是执行在定义成员变量时就对其进行赋值的语句,如:这个图需要画出来在教材中 *执行构造方法中的程序代码 3、finally关键字 *如果在类前加上了finally则不能被继承,成员变量定义成finally子类中不能在对其进行赋值,方法中被定义成finally则在子类中不能对其覆盖,不能再进行改写,final定义的常量不能在其它方法中进行赋值 4、抽象类 java中可以定义一些不含方法体的方法,它的方法体实现交给该类的子类根据自己的情况去实现,这样的方法就是抽象方法,包含抽象方法的类就是抽象类 *抽象类和抽象方法都必须用abstract关键字来修饰 *抽象类不能被实例化,也就是说不能用new关键字去产生对象 *抽象方法只需声明,而不需实现 *含有抽象方法的类必须被声明为抽象类,抽象类的子类必须覆盖所有的抽象方法后才能被案例化,否则这个子类还是个抽象类 5、接口 如果一个抽象类中的所有方法都是抽象的,我们就可以将这个类用另外一种方法来定义,也就是接口的定义。接口是抽象方法和常量值的集合,从本质上讲 接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现 *接口中的成员都是public访问类型的。接口里的变量默认是用public static finall标识的 *我们可以定义一个新的接口用extends关键字去继承一个已有的接口 *我们也可以定义个类用implements关键字去实现一个借口中的所有方法,还可以去定义一个抽象类用implements关键字去实现一个接口中定义的部分方法 *一个类可以继承一个父类的同时,实现一个或多哥接口,extends关键字必须位于implemnets关键字之前 代码解释要点: //类与继承实例 //继承的特点:可以简化类的定义,java中只支持单继承不允许多重继承 class Person { public final String x; //定义为final的常量除了在此处和构造函数中赋初值外,不能在其它地方被赋值,否则编译会报错 /*public static final String x="abc"; */ //另外对于该常量的引用,如果要调用它时,需要首先创建一个对象,如果不创建对象也希望调用它则在final前需要声明为static,这样就可以直接在用classname.varible格式对其访问 //如果这样,则不能在构造函数中对其赋值了,而只能在开始声明的时候进行赋初值,因为在构造函数中赋值的话,调用构造函数的时候,首先会生成一个对象,而此时该static final常量还没赋值所以会报错 public String name="unknown"; public int age=-1; public Person() { x="abc"; //因不知道调用者调用哪个构造函数,所以2个构造函数都被赋初值 } public Person(String name, int age) //子类不会继承父类的构造方法,如果不定义则编译器会自动增加一个不带参数的构造方法,如果自己增加了则编译器不会再增加 { x="abc"; = name; this.age = age; } public void getInfo() { System.out.println("name=" +name+",age=" +age); } } class Student extends Person { public String school="unknown"; public Student() //默认情况下在它调用父类之前会调用此默认构造函数,调用该构造函数之前又会去调用父类的默认构造函数,而此时开发人员已编写了一个带参数的父类构造函数,所以编译器会报错 { super(); //编译器默认调用的为super(),即无参的构造函数 /*super("zhangsan", 15);*/ //super表示明确要调用父类的构造函数,此时编译器不会再报错 } /*public Student(String name, int age) { super(name, age); }*/ public Student(String name, int age, Stringschool) { /*this(name, age);*/ //如果有this()调用则要先执行该类中的Student(Stringname, int age)函数 /*=name; //表明继承了父类的age和name,如果这个2个成员变量为私有的话,就不能这样赋值 this.age=age;*/ super(name, age); //继承用父类的name, age this.school = school; } public void getInfo() { System.out.println("school = " + school+ ", name ="+name+ ", age= " +age); super.getInfo(); //明确调用父类的getInfo } /*public String name; public int age; public void getInfo() { }*/ public void study() { } } class TestStudent { public static void main(String [] args) { Student st = new Student("zhangsan", 20, "清华大学"); //调用的是子类中的getInfo而非父类中的 /* = "zhangshan"; st.age = 20;*/ st.getInfo(); System.out.println(float.MAX_VALUE); //在float类中MAX_VALUE就被声明为 public static finall floatMAX_VALUE } } //抽象类和抽象方法 abstract class A //不是抽象类中所有的方法都是抽象方法,但只要有一个是抽象方法则该类必须为抽象类 { abstract int aa(int x, int y); //注:定义抽象方法直接用";"结束 /*public static void main(String [] args) { A a= new A(); //抽象类中不能被实例化 }*/ } class B extends A { intaa(int x, int y) {return 1; } }