一、面向对象基础apache
1.一、面向对象的定义:ide
定义了一个类就等于定义一种新的数据类型,任何类都是由静态属性和动态属性表示的,函数
静 态的属性经过变量进行存储(属性、实例变量),动态的属性经过函数表示this
(行为、实例函数)。spa
1.1.1 经过new建立一个类的对象指针
1.1.2 经过对象.属性名完成对属性的定义。不能经过类.属性。属性都是属于对象的。code
1.1.3 经过对象.函数名调用这个对象的方法。对象
1.二、面向对象属性的初始化继承
只要是属性,JVM会自动为其赋值。接口
对象类型默认赋值为:String-->null,int-->0,double-->0,char-->空格,boolean-->false。
面向对象的内存模型
1.三、构造函数
构造函数存在的意义是在对象初始化时进行属性的赋值操做。
特色:
一、名称必须和类名彻底一致(包括大小写);
二、不写返回值;
三、当开发人员没有为类写任何构造函数时,JVM会自动生成一个不带参数的构造函数,在这个函数中什么都不作。
四、当开发人员手动写了任意一个构造函数以后,JVM就不会再生成不带参数的构造函数了。
注意:构造函数只是在建立时使用new来调用,不能直接用对象调用。
构造函数也能够设置参数,可是就不会产生不带参数的构造函数,不能再使用new XXX()来建立对象。
1.四、函数重载
函数的名称同样可是参数不一致(类型不一致),就称为函数的重载。
1.五、this指针
在每个对象内部都有一个this指针指向它本身。
调用时,经过this.(点)的方式调用本身内部的属性。
1.六、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.七、对象的初始化顺序
对象初始化顺序
一、初始化属性
二、调用构造方法
public class TestInit { public static void main(String[] args) { Bag bag = new Bag(); } } class Bag { /* * 对象初始化顺序 * 一、初始化属性 * 二、调用构造方法 */ Book b1 = new Book(1); public Bag() { System.out.println("bag"); } Book b2 = new Book(2); }
输出结果:book1,book2,bag.
1.八、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.九、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+")"); } }
二、package:用来解决类名的冲突问题
2.一、package的建立
在有效代码的第一行使用package关键字完成建立
当定义了一个包名以后,表示这个类必须放到包名文件夹中。
在执行程序时,仅仅会默认在当前目录中找当前包中的类,若是但愿找到其它包中的类,须要使用import导入。
2.二、import
在class以前使用import能够导入其它包中的类;
当导入的类有名称冲突须要使用类名的全名访问;
若是使用import org.apache.*;仅仅只会导入org/apache这个文件夹下的全部类,子文件中的类不会被导入。
2.三、包的命名
2.3.一、包名第一个字母用小写。
2.3.二、为了解决冲突问题,通常都是使用域名的反向操做来设置包。
2.四、classpath的设置
设置classpath目的为了让程序能够在classpath的路径下去找包。
三、继承
若是可以经过XXX是XX这样一种话来描述两个class,表示这两个类之间有继承关系,使用extends关键字完成继承,当子类继承了父类以后就会继承父类的属性和方法。
3.1继承的描述
使用extends关键字完成继承,此时具备父类的全部属性和方法。
完成继承后,子类会拥有父类的属性,可是父类不会有子类的属性和方法。
3.二、方法的覆盖
子类的方法名和父类的方法名同样会造成方法覆盖。
3.三、继承的初始化
3.3.一、建立子类以前会先建立父类,默认调用父类不带参数的构造方法。
3.3.二、在构造父类时,默认调用的是不带参数的构造方法,若是没有这个构造方法,会编译报错。
使用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");
四、类的访问控制
public>protected>default>private
private:同一个类中能够访问
default:同一个包中能够访问
protected:不一样包的子类能够访问
public:全部均可以访问
4.一、private:使用private修饰的变量或者方法只能在同一个类中访问。
4.二、default:就是什么都不写,在同一个类和不一样类中均可以访问,不一样的包中没法访问
总结:同一个包中能够访问。
4.三、protected:不一样包中依然没法访问,同一个包中能够访问。
不一样包的子类能够访问
4.四、public:因此地方均可以访问
4.五、最佳实践:
全部类中的属性都是private的,为每个属性增长两个方法getter和setter,全部的getter和setter方法都是public的,
这就是Java Bean的写法。
把全部的属性都设置为private的,而且经过getter和setter方法来分别对应获取值和设置值。这个就是标准的Java Bean
的写法。
五、多态
//父类引用指向子类对象 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;
多态实现的基本条件
一、继承
二、有方法的覆盖
三、有父类引用指向子类对象
六、抽象类和接口
6.一、抽象类
/** * 有一个抽象方法的类就必须是抽象类 * 抽象类不能用来建立对象 * 抽象类所存在的意义,就是用来被继承 * 因此抽象类等于为开发人员肯定了相应的约束 * */ 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.二、接口
接口和类同样,惟一区别就是:接口中的全部方法都是抽象方法,接口中不存在属性,仅仅存在常量,接口中的全部
常量和方法都是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(); }