Java-J2SE面向对象复习

原创
2016/04/23 22:00
阅读数 121

1、面向对象基础

1.1、面向对象的定义:

    定义了一个类就等于定义一种新的数据类型,任何类都是由静态属性和动态属性表示的,

    静 态的属性通过变量进行存储(属性、实例变量),动态的属性通过函数表示

   (行为、实例函数)。

    1.1.1 通过new创建一个类的对象

    1.1.2 通过对象.属性名完成对属性的定义。不能通过类.属性。属性都是属于对象的。

    1.1.3 通过对象.函数名调用这个对象的方法。

1.2、面向对象属性的初始化

 只要是属性,JVM会自动为其赋值。

 对象类型默认赋值为:String-->null,int-->0,double-->0,char-->空格,boolean-->false。

    面向对象的内存模型

    

1.3、构造函数

    构造函数存在的意义是在对象初始化时进行属性的赋值操作。

    特点:

        1、名称必须和类名完全一致(包括大小写);

        2、不写返回值;

        3、当开发人员没有为类写任何构造函数时,JVM会自动生成一个不带参数的构造函数,在这个函数中什么都不做。

        4、当开发人员手动写了任意一个构造函数之后,JVM就不会再生成不带参数的构造函数了。

    注意:构造函数只是在创建时使用new来调用,不能直接用对象调用。

           构造函数也可以设置参数,但是就不会产生不带参数的构造函数,不能再使用new XXX()来创建对象。

1.4、函数重载

    函数的名称一样但是参数不一致(类型不一致),就称为函数的重载。

1.5、this指针

    在每一个对象内部都有一个this指针指向它自己。

    调用时,通过this.(点)的方式调用自己内部的属性。

1.6、Java的内存管理

Person p1 = new Person();
  p1.name = "老张";
  //引用的赋值是将p1所指向的对象赋值给p2
  //此时p1和p2指向同一块内存,所以修改p2等于修改p1
  Person p2 = p1;
  p2.name = "老李";
  p1.show();  //老李
  p2.show();  //老李
  p1 = new Person(); //指向一块新内存
  p2 = new Person(); //指向一块新内存
  //此时name为老李的内存就是垃圾内存,在内存不够用时会自动清理
  
  int a = 10; //基本数据类型的赋值
  int b = a;  //把a的值给b
  b = 30;  //不会修改a的值
  System.out.println(a+","+b); //10,30

        

1.7、对象的初始化顺序
      对象初始化顺序
      1、初始化属性
      2、调用构造方法

public class TestInit {
 public static void main(String[] args) {
  Bag bag = new Bag();
 }
}

class Bag {
 /*
  * 对象初始化顺序
  * 1、初始化属性
  * 2、调用构造方法
  */
 Book b1 = new Book(1);
 public Bag() {
  System.out.println("bag");
 }
 Book b2 = new Book(2);
}

    输出结果:book1,book2,bag.

1.8、static关键字

    static关键字所修饰的属性或者方法都是属于类的,而不是属于对象的,使用类名调用

public static void main(String[] args) {
  Student stu1 = new Student();
  stu1.name = "a";
  //以下调用方式不对,虽然不会报错
  //stu1.claId = 1;
  //应该使用以下方法调用
  Student.claId = 1; //static所修饰的变量用类名调用
  Student stu2 = new Student();
  stu2.name = "b";
  //stu2.claId = 2;
  Student.claId = 2;
  
  stu1.show();
  stu2.show();
 }
}

class Student {
 String name;
 //使用static修饰的关键字是属于整个类的
 //所以为static所修饰的属性赋值或者调用方法建议使用类名调用
 static int claId;
 
 public void show() {
  System.out.println(name+","+claId);
 }

    

    其实static所声明的属性或者函数其实就是全局的函数。

1.9、static的初始化顺序

int num = 10;
 
 public static void main(String[] args) {
  //这句话会报错,因为static所修饰的属性和方法首先会被初始化
  //在初始化该方法时,还没有初始化num
  //num = 30;
  new People();
 }
}

class People {
 Study s1 = new Study(1);
 public People() {
  System.out.println("people");
 }
 //static所声明的变量首先被初始化
 static Study s2 = new Study(2);
}

class Study {
 Leaf l1 = new Leaf(1);
 Study(int page) {
  System.out.println("study["+page+"]");
 }
 //static所修饰的变量仅仅只会初始化一次
 static Leaf l2 = new Leaf(2);
}

class Leaf {
 public Leaf(int page) {
  System.out.println("leaf("+page+")");
 }
}

2、package:用来解决类名的冲突问题

2.1、package的创建

    在有效代码的第一行使用package关键字完成创建

    当定义了一个包名之后,表示这个类必须放到包名文件夹中。

    在执行程序时,仅仅会默认在当前目录中找当前包中的类,如果希望找到其它包中的类,需要使用import导入。

2.2、import

    在class之前使用import可以导入其它包中的类;

    当导入的类有名称冲突需要使用类名的全名访问;

    如果使用import org.apache.*;仅仅只会导入org/apache这个文件夹下的所有类,子文件中的类不会被导入。

2.3、包的命名

    2.3.1、包名第一个字母用小写。

    2.3.2、为了解决冲突问题,一般都是使用域名的反向操作来设置包。

2.4、classpath的设置

    设置classpath目的为了让程序可以在classpath的路径下去找包。

3、继承

    如果能够通过XXX是XX这样一种话来描述两个class,表示这两个类之间有继承关系,使用extends关键字完成继承,当子类继承了父类之后就会继承父类的属性和方法。

    3.1继承的描述

        使用extends关键字完成继承,此时具有父类的所有属性和方法。

        完成继承后,子类会拥有父类的属性,但是父类不会有子类的属性和方法。

        

    3.2、方法的覆盖

        子类的方法名和父类的方法名一样会形成方法覆盖。

    3.3、继承的初始化

        3.3.1、创建子类之前会先创建父类,默认调用父类不带参数的构造方法。

        3.3.2、在构造父类时,默认调用的是不带参数的构造方法,如果没有这个构造方法,会编译报错。

        使用super关键字解决以上问题

        super一定要在构造函数的第一行

class School {
 public School(String str) {
  System.out.println(str);
 }
 
 public School() {
  System.out.println("school");
 }
}

class MiddleSchool extends School {
 Student stu = new Student();
 public MiddleSchool() {
  //super一定要在构造函数的第一行
  super("abc"); //调用父类带参数的构造函数
  System.out.println("middle");
 }

        super的使用

//super一定要在构造函数的第一行
  super("abc"); //调用父类带参数的构造函数
  System.out.println("middle");
  //调用父类的构造方法
  super.test("kkk");

4、类的访问控制

    public>protected>default>private

    private:同一个类中可以访问

    default:同一个包中可以访问

    protected:不同包的子类可以访问

    public:所有都可以访问

    4.1、private:使用private修饰的变量或者方法只能在同一个类中访问。

    4.2、default:就是什么都不写,在同一个类和不同类中都可以访问,不同的包中无法访问

        总结:同一个包中可以访问。

    4.3、protected:不同包中依然无法访问,同一个包中可以访问。

        不同包的子类可以访问

    4.4、public:所以地方都可以访问

    4.5、最佳实践:

        所有类中的属性都是private的,为每一个属性增加两个方法getter和setter,所有的getter和setter方法都是public的,

        这就是Java Bean的写法。

        把所有的属性都设置为private的,并且通过getter和setter方法来分别对应获取值和设置值。这个就是标准的Java Bean

        的写法。

5、多态

//父类引用指向子类对象
  Person p = new Student();
  p.name = "李四";
  p.show();
  //由于p这个对象实际是指向student的,所以此处可以使用强制类型转换将其转化为student
  Student s = (Student)p; 
  //由于引用p是指向了一个具体的student对象,所以可以进行强制类型转换
  s.no = "123";
  s.show();
  
  //p2指向的是父类对象,所以无法强制类型转换为子类对象
  Person p2 = new Person();
  Student s2 = (Student)p2;

    

    多态实现的基本条件

    1、继承

    2、有方法的覆盖

    3、有父类引用指向子类对象

6、抽象类和接口

    6.1、抽象类   

/**
 * 有一个抽象方法的类就必须是抽象类
 * 抽象类不能用来创建对象
 * 抽象类所存在的意义,就是用来被继承
 * 所以抽象类等于为开发人员确定了相应的约束
 *
 */
public abstract class Pet {
 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
 
 /**
  * 该方法存在的意义只有一个:就是用来被子类覆盖
  * 这种方法,可以声明为抽象方法
  * 有一个抽象方法的类就是抽象类
  */
 public abstract void enjoy();
}

    6.2、接口

        接口和类一样,唯一区别就是:接口中的所有方法都是抽象方法,接口中不存在属性,仅仅存在常量,接口中的所有

        常量和方法都是public的。

        通过关键字interface来完成接口的创建。

        由于接口中所有的方法都是抽象和public的,所以可以省略abstract和public关键字,但是建议的方式是:

        不要省略public而省略abstract。

public interface Studyable {
 public void study();
 //用下面的方式同样可以定义接口,和上面方式完全一样
 //public abstract void study();==void study();  
}

        子类通过实现来替代继承(也就等于继承)。

//接口支持多实现
public class Student implements Studyable, Talkable {
 //需要实现接口中的所有方法
 
 @Override
 public void talk() {
  System.out.println("talk");
 }

 @Override
 public void study() {
  System.out.println("study");
 }

    实现和继承基本类似,都是支持多态的。

public static void main(String[] args) {
  Talkable ta = new Student();
  ta.talk();
  Studyable sa = (Studyable)ta;
  sa.study();
  
  Student stu = (Student)ta; //Student stu = (Student)sa;
  
  stu.talk();
  stu.study();
 }

    

展开阅读全文
打赏
1
3 收藏
分享
加载中
更多评论
打赏
0 评论
3 收藏
1
分享
返回顶部
顶部