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了!