java基础笔记-面向对象1


四 面向对象

1.类的基础

1.1类的结构

class Person{
	成员属性
    成员方法
}
Person p = new Person();

1.2 匿名对象

new Student().toString();

2.类的方法

2.1方法的局部变量

? 成员方法的局部变量,没有默认初始化赋值,必须显式的赋值

? 形参,也是局部变量,但是,不需要初始化赋值!!!调用时赋值即可

2.2成员方法的内存加载位置

? 类的成员属性,加载在heap中,(static除外)

? 但是方法的局部变量,加载在栈空间

2.3方法的重载 overload

? 在同一个类里面,允许存在多个同名函数,只要参数列表不一样 (与返回值无关!)

2.4 可变个数形参

? 0到多个都行

? 但是必须声明在形参列表的最后

public void show(String ... str){
}
public void show(String str){ //可以共存 ,如果只传一个参数,编译器会选这个方法
}
public void show(String[] str){//不行,编译器会认为相同,同时这个也是1.5之前jdk处理可变个数参数的办法
}

3.封装

? 高内聚,低耦合

3.1 权限

? 类成员的权限

? private,缺省,protected,public

修饰符 类内部 同一个包 不同包的子类 不同包
private Y
缺省 Y Y
protected Y Y Y
public Y Y Y Y

? class 的权限只有public和缺省两种

? public类可以在任意地方被访问

? 缺省类,只能被同一个包下的类访问

4.构造器,构造方法 constructor

? 构造方法,不算方法。。。

? 提供了有参构造方法之后,默认的无参构造方法就失效了,除非再定义一个无参的(重载)

class Person{

	public Person(){
		sout;
	}
}

4.2 this调用构造器

1.一个类有n个构造方法,则最多有n-1个构造方法可以使用this();

? 防止循环调用

2.每个构造方法里面最多放一个this();

class Person{
	private String str;
    private int num;
	public Person(){
		sout;
	}
    public Person(String str){
        this();
    }
        public Person(String str,ing num){
        this(str);// 调用了第二个构造方法
        this.num=num;
            
    }
}

5.继承

5.1 重写override

? 父类被重写的方法的返回值是void或者基本类型,子类重写方法不能改变

? 父类被重写的方法的返回值是引用类型,子类重写方法的返回值只能是该引用类型或者其子类

? 父类的static方法不能被继承,除非子类也是static(就不是重写了)

? 重写方法的权限只能变大,父类的private方法不能被重写

5.2 super

? 注意:同名id,就近一致

? super()必须在子类构造方法的首行

? super()和this() ,只能出现一个,不能同时出现,都不写的时候,默认调用父类的空参构造方法

class Fu{
    private int a;
    private int id;
    public Fu(int a,int id){
        this.a = a;
        this.id = id;
    }
}
class Zi extends Fu{
    private int b;
    private int id;
    public Zi(int a , int b,int id1,int id2){
        super(a,id1);
        this.b=b;
        this.id=id2;
    }
}

5.3 内存夹杂

? 子类在实例化时,会在对空间中加载父类的所有能获得的属性

6. 多态 Polymorphism

6.1 基础

? 多态是个运行时行为

? Fu fu =new Zi()

6.2 虚拟方法调用

多态:调用子父类重写的方法,是实际执行的是子类的方法,成为虚拟方法调用(在IDE中ctrl左键查看方法声明时,会打开父类的方法)

编译看左边,运行看右边(编译时看左面的变量类型,运行时执行的是右边的类的方法)

public class Person{
    int age;
    String name;
    public void eat(){
        sout("eat");
    }
}
public class Man extends Person{
    boolean isSmoking;
    public void smoke(){
        sout("smoke");
    }
    public void eat(){
        sout("Man eat");
    }
}
public class Woman extends Person{
    int height;
    public void eat(){
        sout("Woman eat");
    }
}

public static void main(String[] args){
    //多态,
   	Person p= new Man(); 
    p.eat()
    p.smoke()//报错的,因为p是没有smoke方法的
}

6.3 为啥用多态

? 很少有直接写Fu fu =new Zi()的

? 其实都用在了哪呢:方法的形参传递里面了(声明的是父类,传入的是子类的对象)

? 再就是返回值也是这样,方法声明返回值是父类,但是代码内部new了一个子类对象返回了

? 例1:

? equals(Object obj);

? 例2:

java连接数据库时,java提供的接口方法是统一的,但是不同的数据库厂商的具体执行方法是不一样的,所以要求不用的厂商重写java提供的父类方法

import java.sql.Connection;
public void do(Connection conn){
  	pass;
}
psvm(){
    Connection conn1 = new MySQlConnection();//不同数据库
    do(conn1);
    Connection conn2 = new OracleConnection();//不同数据库
    do(conn2);
}

6.4 向下转型 instanceof

? 多态的对象,不能调用子类特有的方法和属性,如上面的smoke方法

? 注意,子类的方法已经加载进内存了,只不过声明的类型导致调用不了

? 所以需要转型

Fu fu = new Zi();
if(fu instanceof Zi ){ //不判断可能遇到ClassCastException的异常
    Zi zi = (Zi)fu;
}

a instanceof A:判断对象a是否是类A

7. Object和包装类

java.lang.Object

7.1 equals( Object obj ) 和 ==

equals( Object obj ) 比较俩对象的地址,底层用的就是==

但是String类里面对equals重写了,比较的就是字符串的值,Date,File,各种包装类也一样,都重写了

class Objet{
    public boolean equals(Object obj){
        return (this == obj)
    }
}

== 引用类型比较的是地址,基本数据类型比较值

注意:

int  i = 10;
double j = 10.0;
sout(i == j)//true,因为自动类型提升了

7.2 toString( )

当输出一个对象的引用的时候,实际上就是调用了对象的tostring( )方法

public String toString() {
	return getClass().getName() + "@" + Integer.toHexString(hashCode());//计算对空间中的hash值找到位置,再转十六进制,再转Int
}

String,Data,File ,包装类也都重写了toString方法

7.3 包装类Wrapper

Byte,Short,Integer,Long,Float,Double,Boolean,Character

转换:

基本数据类型----装箱------>包装类:Integer i= 9;即可(自动装箱),new Integer(9)已经过时了

包装类----------拆箱---------->基本数据类型: int i = 直接赋值一个Integer就行 (自动拆箱)

包装类-------->String : Integer in =9; in.toString()

String--------->包装类: Integer.valueOf("21");

String -------->基本数据类型: Intger i = Integer.parseInteger("123");

基本数据类型------->String: String str = String.valueOf(3.4f);

7.4 自动装箱 拆箱

Integer i =new Integer(9);
Integer j =new Integer(9);
sout(i == j); //false


Integer n =1;
Integer m =1;
sout(m == n); //true
//自动装箱,

Integer x = 128
Integer y = 128;
sout(x == y); //false
//Integer里面有个Integer的静态内部类IntegerCache
// 里面存了个Integer[] -128到127
//如果使用自动装箱的方式,给Integer赋值在这个范围内的数都直接使用这个数组里面的(static),不用再去new了!