首页 > 代码库 > Java 面向对象
Java 面向对象
类:
是构造对象的模板或蓝图;
类构造对象的过程称为创建对象的实例;
用Java编写的所有代码都位于某个类的内部;
封装:
将实例域(属性)和方法包在一起;
对对象的使用者隐藏了数据的实现方式;
关键在于:绝对不能让类中的方法直接地访问其它类的实例域,程序仅通过对象的方法与对象数据进行交互;即使用方法将类的数据隐藏起来,控制其他类对该类的修改和访问数据的程度;就是说,一般获取、修改对象的属性都是通过方法来操作;
对于每个特定的实例(对象)都有一组特定的实例域值,这些值的集合就是这个对象的当前状态;
优点:针对域
避免域被其他类的方法直接访问;(所以一般都定义为私有的,只通过本类中的方法进行调用和修改)
可以改变内部实现,除了该类的方法之外,不会影响其他代码;
更改器方法可以执行错误检查;
注意:
不要编写返回引用可变对象的访问器方法;如果需要返回一个可变对象的引用,应该首先对它进行克隆;
继承:
子类会继承父类所有的内容(包括所有属性和方法,但不包括构造方法),但不一定能直接使用;
java只支持单继承,extends后面只能跟一个类;
举例:
类B继承类A;
类B创建的实例,可以调用和类A中相同的公有的方法和公有的实例域;但不能调用或设置类和A中相同的私有实例域和私有方法;
一个类的所有对象,每个对象都有自己的一份实例域,但所有对象共用那些方法;
继承的特性:
1.当一个类继承自另一个类,子类中没有显式定义和父类相同的方法(方法名、参数、返回值都一样)时。用子类的对象调用方法时,会首先在子类中查找,如果子类中没有该方法,再到父类中查找。
实例(1):
1 public class Demo1 2 { 3 // 父类定义的 print()方法 4 public void print() 5 { 6 System.out.println(123); 7 } 8 } 9 10 11 public class Demo2 extends Demo1 12 { 13 // 子类没有显式定义和父类相同的方法(方法名、参数、返回值类型都一样) 14 } 15 16 17 public class Test 18 { 19 public static void main(String[] args) 20 { 21 Demo2 demo = new Demo2(); 22 // 最后打印出的结果是 123 23 demo.print(); 24 } 25 }
实例(2):
public class Demo1 { // 父类定义的 print()方法 public void print() { System.out.println(123); } } public class Demo2 extends Demo1 { // 子类显式定义和父类相同的方法(重写) public void print() { System.out.println(456); } } public class Test { public static void main(String[] args) { Demo2 demo = new Demo2(); // 最后打印出的结果是 456 demo.print(); } }
2.子类与父类之间构造函数的使用规则:
(1).Java中每个类都有一个构造函数;如果类中没有显式定义构造函数,则编译器会默认提供一个无参构造函数;
(2).子类继承父类时,必须在构造函数中调用父类的构造函数;
(3).父类没有显式定义构造函数,只有一个默认的无参构造函数,那么子类继承父类时,也是通过在默认的无参构造函数调用父类的构造函数;
public class Demo1 { /** * 这是编译器默认提供的无参构造函数 * 这个构造函数是隐藏的,看不到,现在让它显式出来只是为了看到无参构造函数的样子 * 这里的super()调用的是 Object 类的构造方法 * 父类并没有显式定义构造函数 */ public Demo1() { super(); } } public class Demo2 extends Demo1 { /** * 子类继承父类,通过编译器提供的默认构造方法调用父类的构造方法 * 这里构造方法也是隐藏的 * 这里的 super() 调用的是 Demo1 类的构造方法 */ public Demo2() { super(); } }
(4). 父类显示定义了带参(必须是带参)构造函数,那么子类继承父类时,也必须显示定义一个带参构造函数,在这个构造函数中调用父类的构造函数;
public class Demo1 { /** * 父类显示定义了一个带参构造函数 */ public Demo1(String s) { super(); System.out.println(s); } } public class Demo2 extends Demo1 { /** * 子类必须显示定义一个带参构造函数来调用父类的构造函数 * 这里的 super(s) 就是调用父类的带参构造函数,s是实参 */ public Demo2(String s) { super(s); } }
3.当一个方法只在父类中定义时,调用该方法时使用到的属性是父类的属性;如果该方法中又调用了其他方法,那么还是按照之前的顺序,先在子类中查找,再在父类中查找。
public class Demo1 { int x = 6; private int y = 2; public Demo1(int a) { x = a; } int getz() { int z; z = x / y; return z; } void show() { System.out.println("x=" + x); System.out.println("y=" + y); // 方法中调用了其它方法 System.out.println("z=" + getz()); } } public class Demo2 extends Demo1 { // 重新定义了 x,y 变量 int x = 3, y = 5, z; public Demo2(int a) { super(a); } // 重写了 getz() 方法 int getz() { z = x + y; return z; } // 定义独有的方法 public void print() { System.out.println("x = " + x); System.out.println("y = " + y); System.out.println("z = " + z); } } public class Test { public static void main(String[] args) { Demo1 demo1 = new Demo1(10); Demo2 demo2 = new Demo2(9); demo1.show(); /** * 打印出的结果: * x=9:子类 Demo2 通过构造方法将父类 Demo1 中的 x 属性值设为9,子类对象调用的 * show() 方法在子类中没有重新定义(重写),调用的是继承自父类的 show()方法, * 则在父类中的 show() 方法中调用的 x 属性就是父类中的属性,值为 9; * y=2:同样的道理,子类调用的 show() 方法在子类中没有重新定义,所以 show() 方法 * 中调用的 y 属性是父类中的 y 属性,值为 3; * z=8:show() 方法中的 getz() 方法在子类和父类中都有,则优先调用子类中的 getz() * 方法,那么子类中的getz()放用到的 x,y,z 属性就是子类中定义的 x,y,z 属性,x,y 的 * 值分别为 3和5,所以 y 计算出来的值是 8; */ demo2.show(); /** * 调用子类特有的方法,那方法里面用的属性都是子类重新定义好的属性 */ demo2.print(); } } // 最后打印出的结果: // x=10 // y=2 // z=5 // x=9 // y=2 // z=8 // x = 3 // y = 5 // z = 8
Java 面向对象