您的位置:首页 > 职场人生

黑马程序员——JAVA基础之面向对象(下)

2015-08-23 11:16 344 查看

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

  上篇博客讲述了面向对象三大特征之一的封装,接下来将讲述省下的继承,多态以及其他的一些知识点。

一、面向对象中的static

  static是一个修饰符,用来修饰成员变量以及成员函数。被修饰的成员的数据将不再存放在堆内存中,而转移到方法区中,并且所有对象都指向同一个值。而且不需要对象,直接用类名就能使用这个成员。一下代码将演示static的一些特性:

class student {
int age;
String name;
static String country = "CN";//使用static关键字修饰成员变量
}
public class Test {

public static void main(String[] args) {
System.out.println(student.country);//使用类名调用被static修饰的变量
student s1= new student();
System.out.println(s1.country);     //使用对象调用变量
student.country = "a";		    //修改被static修饰的变量
System.out.println(s1.country);     //修改完后输出

}

输出结果为” CN CN a“,可以发现当改变了被stiati修饰的country的值后对象的值也被改变了。


二、类的继承

  类的继承是面向对象的另一大特征,继承能提高代码的复用性,能让类与类之间产生关系,有了这个关系,才有了多态的特征。接下来将用代码演示继承的基本使用方法。

class A{
//定义一个基类
int num =1;
void show(){
System.out.println(num);
}
}

class B extends A{
//定义一个类仅继承A,其余不写任何内容
}
public class Test {

public static void main(String[] args) {
B b = new B();//实例化子类B
b.show();//虽然B类可以使用父类A中的方法
}
}

  虽然B类并没有内容,但是由于继承了A类,可以调用A类中所有成员变量以及方法,运行show方法将在控制台打印“1”。需要注意的是java只支持单继承,不支持多继承。不过java可以多层继承,也就是说可以定义一个C类来继承B类,也可以调用A类中所有成员变量以及方法,就不用代码演示了。
  说完基本的继承应用接下来说说复杂点的,如果子类中出现和父类一样名字的变量、函数以及都有构造函数改如何区分呢?若子类与父类中成员变量拥有同样的变量名,则在子类中若想调用父类的变量内容需要添加super关键字,若想调用本身的变量则可添加this关键字或不添加,下面用代码演示:

class A{
//定义一个基类
int num =1;
}

class B extends A{
int num = 2;//定义一个类来继承A类,且与父类有一个相同变量名但内容不同的变量
void show(){
System.out.println(super.num);//添加suoer关键字将输出父类中的内容
System.out.println(num);//不添加关键字将输出子类中的内容
System.out.println(this.num);//添加this关键字将输出子类中的内容
}
}
public class Test {

public static void main(String[] args) {
B b = new B();
b.show();
}
}

  输出结果为“1   2   2”。
  若子类与父类中函数拥有相同的函数名且入参相同时,子类会覆盖父类的函数,称之为重写,若在子类中想调用父类中的函数与调用变量一样需要添加super关键字,由于与调用变量内容大致相同,就不演示了。
  若子类与父类都有构造函数,则在对子类对象进行初始化,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式的语句super(),super()会访问父类空参数的构造函数,而且子类中所有的构造函数默认第一行都是super()。之所以默认第一行是为了查看父类如何进行数据初始化的,以便子类可以在构造函数内调用父类的变量。请看代码演示:

class A{
//定义一个基类
A(){
//定义一个空入参的构造函数
System.out.println("A");
}
A(int X){
//定义一个带有入参的构造函数
System.out.println("X");
}
}

class B extends A{
//定义一个类来继承A
B(){
//由于继承了A所以这里其实隐藏了一行super();作用是调用父类空入参的构造函数
System.out.println("B");
}
}
public class Test {

public static void main(String[] args) {
B b = new B();
}
}
  以上代码输出结果为“A B”。也就是说实例化子类B时先运行了父类A中的空的构造函数再运行子类本身的构造函数,并不会运行带有入参的构造函数。


三、抽象类


  在java中被abstract关键字修饰的方法没有方法体,该方法的实现由子类完成,称之为抽象方法,包含抽象方法的类就是抽象类。抽象类不可以被实例化,也就是不可以用new创建对象。抽象类需要通过子类来实例化,子类必须实现父类所有抽象的方法。下面演示抽象方法基本应用:
abstract class person {
//定义一个抽象类
private String name;
private String age;
abstract void say();//拥有一个未实现的方法,也就是抽象方法
}
class Chinese extends person{
//定义一个类来继承抽象类
@Override
void say() {
//子类继承抽象类必须实现所有抽象方法
System.out.println("你好");
}
}
class American extends person{
//同上
@Override
void say() {
System.out.println("hello");
}

}

public class Test {

public static void main(String[] args) {
Chinese a = new Chinese();//抽象类需要通过子类来实例化
a.say();//调用say方法
American b = new American();//同上
b.say();
}
}
  输出结果为“你好  hello”。

  四、接口


  接口可以被认为是一个特殊的抽象类。如果抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。接口使用interface来表示,子类中用implements实现。接口中变量默认添加修饰符[public]、[static]、[final],方法默认添加修饰符[public]、[abstract]。
  接口与类有几点不同:1、接口可以用来多实现。这也是对多继承不支持的转换形式。java支持多实现。2、类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。3、接口与接口之间可以有继承关系。而且可以多继承。下面用代码演示下简单应用:
interface A{
//定义一个接口
int NUM =30;//相当于public static final int NUM = 30
void a(); ////相当于public abstract a()
}
interface C{
//定义另一个接口
String name ="张三";
}
class B implements A,C{
//定义一个类来多实现接口A和C
@Override
public void a() {
//实现家口必须实现接口内所有抽象方法
System.out.println(name);//由于实现了C接口,所以可以使用name常量
}

}
public class Test {

public static void main(String[] args) {
B b = new B();
b.a();//将在控制台打印“张三”
}
}

五、类的多态


  面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。多态是指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。多态能够消除类型之间的耦合关系。
  函数的多态有两种表现形式:重载和覆盖。
  重载(overload),是发生在同一类中。与什么父类子类、继承毫无关系。标识一个函数除了函数名外,还有函数的参数(个数和类型)。也就是说,一个类中可以有两个或更多的函数,叫同一个名字而他们的参数不同。下面用例子演示重载

class A {

3ff7
//定义一个类,含有两个入参不同方法名相同的方法
public void show(int X){

}
public void show(String Y){

}
}
  覆盖(override),是发生在子类中,也就是说必须有继承的情况下才有覆盖发生。我们知道继承一个类,也就有了父类了全部方法,如果你感到哪个方法不适用,功能要变,那就把那个函数在子类中重新实现一遍。这样样再调用这个方法的时候,就是执行子类中的过程了。父类中的函数就被覆盖了。
class A {
public void show(int X){
System.out.println("A and X");
}
}
class B extends A{
//定义一个类继承A,重写方法show
public void show(int X){
System.out.println("B and X");
}
}
  对象的多态性:父类 X = new 子类(),子类转型成父类是向上转型,反过来说,父类转型成子类就是向下转型。也就是说:子类 Y = (子类) new 父类()。接下来将用代码演示:
abstract class person{
//定义一个person抽象类,拥有抽象方法want
String name;
int age;
abstract void want();
}
class student extends person{
//定义一个类来继承person类
void learning(){
//定义一个子类独有的方法
System.out.println("成绩提升");
}
void want(){
//实现所有父类中的抽象方法
System.out.println("想要成绩");
}

}

public class Test {

public static void main(String[] args) {
person a = new student();//此为向上转型
a.want();
//此时无法调用student内独有的方法a.learning()
student b = (student) a;//此为向下转型
b.learning();//可以调用子类独有的方法
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: