您的位置:首页 > 编程语言 > Java开发

Java-J2SE面向对象复习

2016-04-23 00:00 232 查看
摘要: Java J2SE 面向对象

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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  J2SE 面向对象 Java