面向对象的理解和封装
通过抽象实例的思维,对具体事物的抽象,抛开东西的具体实现,只关心抽象的事物的属性和方法。而封装则是通过访问权限修饰符的合理的暴露相应的方法和属性。
public class Person{
//描述对象具有的属性,应根据需求提供getter和setter方法。
private String name ;
private int age ;
//描述对象具有的方法,当调用时调用者只关心你能做什么,而不是你怎么去做。
public void see(){}
public void say(){}
public void work(){}
}
面向对象中的封装,追求的是“高内聚,低耦合”
- 内聚:程序内的各个模块之间的关系紧密程度
- 耦合:外部程序(子程序)之间的关系紧密程度
面向对象的内存分析
- 栈:栈是由系统自动分配,相对读写速度快,用于存放局部变量的信息(地址或者数据),每个线程私有,不能实现线程间的共享
- 堆:用于存放生成的对象的成员信息,是一个不连续的内存空间,相对读写速度慢。
- 方法区:被所以线程所共享:存放加载的类信息,static field, 和常量池 。
this在对象的成员变量中创建生成,用于存放引用,方便调用。
构造器(constructor)
构造器是用于对象的属性初始化,并且和new关键字连用用于创建对象
- 当不需要重载构造器时,类中默认生成了写有无参的构造器,用于被调用创建对象。
当写人了重载的构造器,类中的无参构造器就没有了,需要手动添加
当没有指定this或者super调用本类或者子类的构造器是,构造器中首句都默认的指行了super();方法调用父类的无参构造器
public class Person{
private String name ;
public Person(){
super() ;
}
public Person(String name){
super();//有系统默认生成,不管写没写都会有
}
}
- 所以在考虑本类是否会被继承的情况应在大部分的时候提供无参构造器让子类调用相应的构造器
public class Person{
private String name ;
public Person(){
super() ;
}
public Person(String name){
super();
}
}
public class son extends Person{
private String name ;
private int age ;
private String sex ;
public Person(){
super() ;
}
public Person(String name){
super(name);//也可以指定父类的构造器这样在不考虑其他本类的其他构造器的情况下,父类可以不写无参构造器。
}
public Person(String name , int age){
super(name) ;
this.age = age ;
}
public Person(String name , int age , String sex){
this(name , age) ;//也可以指定this关键字调用本类的构造器,但super的首位还是会被放在调用的构造器中,也就是说子类的构造器总是会调用父类的构造器一次
this.sex = sex ;
}
}
Method Overriding
- 方法名,返回值,参数类型一致。
- 访问权限修饰符要大于等于父类方法的权限。
- 返回值类型: 基本变量的返回值类型要一致,但引用类型的返回值可以是返回值的子类类型。
- 抛出的异常要比父类的范围小或者相等。
注:如果不加注解检查重写,有些错误的写法,只会是被当作重新定义了一个方法,常表现在想要重写子类无法访问的方法,或者参数不一致的方法。
继承和组合
继承是继承父类中所有的成员变量和方法(不考虑final的情况),但不继承构造器。但是在生成对象后,子类生成的引用具有父类体系中所有的成员信息,但是访问和继承使用时,要考虑访问权限的问题,虽然继承了属性但是无法访问到。
- 父类main方法可以被继承,但是子类没有办法用他作为程序的入口。
- 当子类想要区分子类和父类的方法或变量时,用this和super区分。
组合的方式代替继承
- 典型的使用:System.out.println() ;System的类中构建了用于输出的PrintStream对象out,这样就具有的out的方法
java的方法绑定
java的绑定分为静态绑定和动态绑定,静态的绑定发上呢个在编译时期,动态的绑定发生在运行的时期。
静态绑定
- 在编译期完成,可以提高代码执行速度。静态绑定的方法包括:静态方法,构造器,private方法,用关键字super调用的方法
动态绑定
通过对象调用的方法,采用动态绑定机制。 这虽然让我们编程灵活,但是降低了代码的执行速度。这也是JAVA比C/C++速度慢的主要因素之一。
多态
多态性是OOP中的一个重要特性,主要是用来实现动态联编的,换句话说,就是程序的最终状态只有在执行过程中才被决定而非在编译期间就决定了。这对于大型系统来说能提高系统的灵活性和扩展性。
- 多态的必要条件 : 继承,重写,父类引用指向子类对象 ;
- 多态的成员共享问题和多态的内存做法
package object.poly;
public class Test{
public static void main(String[] args) {
Person p1 = new A("A") ;
Person p2 = new B() ;
p1.say() ;//输出 I am A
p2.say() ;//输出 I am B
//p1.work() ;该方法无法执行,当用父类接受子类创建的对象时,该对象无法执行子类的扩展的方法,只能执行子类重写过或者继承的方法
//在多态中,父类接受子类创建的对象,没有办法接受子类的属性,在内存中子类的方法被隐藏,所以如果强制转换时才可以使用。
A a = (A)p1 ;//此时A的name信息和其他方法才能被访问。
a.work() ;
System.out.println(a.getName()) ;
}
}
class Person {
public void say(){
System.out.println("say.....");
}
}
class A extends Person{
private String name ;
public String getName() {
return name;
}
public A(){}
public A(String name) {
super();
this.name = name;
}
public void say(){
System.out.println("I am A");
}
public void work(){
System.out.println("A的方法");
}
}
class B extends Person{
public void say(){
System.out.println("I am B");
}
}
向上转型和向下转型
- 向上转型基本类型和引用类型都可以自动转型。
- 向下转型:基本数据类型 都可以但是有可能会损失精度 , 引用数据类型 存在向上转型才可以向下转型,也就是说引用类型必须是该对象的实例才可以向下转型 。
final 关键字
package object.two;
public class TestFinal {
//fianl修饰static成员表示的是一个常量。必须要在类加载时初始化,也就是static修饰或者在静态代码块中初始化变量。
public static final int NUM = 1 ;
//final修饰的成员变量必须要在对象创建是初始化,也就是指定放在代码块初始化,或者构造器中
public final int num2 ;
{
num2 = 2 ;
}
public final void show(){
System.out.println("该方法被final修饰,子类继承无法被重写") ;
}
}
final class B{
//final修饰的类无法被继承。
//所以常用的工具类或者系统类都是不希望被继承重写。大多都是用final修饰,或者私有其构造器
//如Math , System 类都是final修饰,例外还有Arrays类虽然没有被final修饰,但也私有了构造器,Arrays工具类没有用final修饰的原因是因
//为Arrays的一个内部类中定义了一个数组,需要指定的初始化。
}
包的命名规则
- com/org/cn.company.project.module.submodule.xxx
Object类
Object是所有类的基类,内部方法大致分为:底层调用其他语言实现的方法(native关键字修饰方法,用于注册,和线程控制等) ,对象(equals,toString)方法。以及用于提醒虚拟机垃圾回收的finalize方法 ;