CoreJava

java面向对象部分
一、面向对象三大特征
1.封装 - 针对属性而言,即属性的封装
定义:将类的属性封装起来,通过公有的方法进行属性的赋值,并在方法中进行一
定的逻辑判断,再通过公有的方法进行属性的取值
步骤:
1). 属性设置为private
2). 提供public 方法进行读写操作
属性的封装,注意构造方法:
public MyDate(int year,int month,int day){
//如下才是完全意义上的封装
setYear(year);
setMonth(month);
setDay(day);
/**如果是:
this.year = year;
this.month = month;
this.day = day;
则是假封装
*/
}
2.继承 - is a 的关系
extends:java 中用extends 关键字来表示一个类继承另一个类
单继承:java 中类和类之间是单继承,只能有一个直接父类
继承什么:只有private 和构造方法不可以被继承,其它的均可以被继承,对于静态属性或方法虽然被继承了,但依旧属于父类而不从属于子类继承这里注意super 关键字的使用

3.多态 - 一个事物的多种形态
3.1多态的四种情况
1. 基本类型的多态
2. 方法的多态(同名方法的多种形态,从而进行重载或者重写)
3. 类或者接口的多态(Person p = new Teacher(),此时Person 是类,or Person p =new PersonImp(),此时Person 是接口)
4. 参数的多态(涉及到类型自动提升,实质也是基本类型或类和接口的多态)
3.2 两个定理
一般情况下的多态说的是方法、类或者接口的多态,因此请记住:
1). 如果把子类对象当作父类对象来看,那么就只能访问父类中有定义的属性和方法;
2). 如果子类将父类的方法覆盖了,而把子类对象当作父类对象来看,再调用该方法时,其实调用的是覆盖后的方法。
例:
Person p = new Teacher(); // 如果在子类覆盖了父类的Test()方法,当p.test()时,访问的是子类中覆盖了父类中的test()方法
3.3注意事项
1. p 只能访问Person 的属性和方法(私有),以及子类中覆盖了父类的方法
2. 如果想访问Teacher 类中的属性和一般方法,只能对p 进行强制类型转换
3. 如果想访问Person 类中已经被覆盖的方法,可在子类的覆盖方法中加上super.test()
3.4 instanceof
判断某个引用变量指向对象是否是某个类的实例(向父类进行兼容,在类型转换前,要
加上类型转换判断。)
public void test(Object obj){
if(obj instanceof Person){
Person p = (Person)obj;
}
... ...
}
注意:在类的类型转行前要加上instanceof,这样就不会再有ClassCastException 异常了

二、重写
当父类的方法不能满足子类的要求时,需要对父类的方法进行重写(重写也叫做覆盖)
要求:
方法名相同
参数列表相同
返回类型相同(从jdk5 开始,返回类型可不同)
访问权限不能比父类更小
不能抛出比父类更大的异常
例:从J2SE5.0 开始在重新定义方法时,您可以重新定义返回值的型态重新定义的返回
值型态必须是父类别中同一方法返回型态的子类别
public class Bird {
protected String name;
public Bird(String name) {
this.name = name;
}
public Bird getCopied {
return new Bird(name);
}
}
public class Chicken extends Bird{
protected String crest;
public Chicken(String name,String crest){
super(name);
this.crest = crest;
}
public Chicken getCopied(){ //重新定义返回值类型为Chicken
return new Chicken(name,crest);
}
}


三、static
1. 修饰谁:用于修饰属性、一般方法、内部类、语句块的
2. 意义:用static 修饰的是类相关的,放在方法区(或者将方法区池化,说池中也可)不加表示实例相关的(池:常驻内存,即使对象消失,池也存在)
3. 静态变量和实例变量的区别:
3.1 静态变量在内存中只有一个拷贝,运行时java 虚拟机只为静态变量分配一次内存,在加载类的过程中完成静态变量的内存分配,可以通过类名直接访问静态变量
3.2 对于实例变量,每创建一个实例就会为实例变量分配一次内存
4. static 变量的作用:
4.1 能被类的所有实例共享,可做为实例之间进行交流的共享数据
4.2 如果类的所有实例都包含一个相同的常量属性,可把属性定义为静态常量类型,从而节省内存空间
5. 何时静态属性申请池空间(即方法区)?
答:在类加载时静态属性和静态方法申请池空间
6. 何时进行类加载?
答:1. 创建类的实例,new Xxx();
2. 调用类的静态方法或类的(接口的)的静态变,Xxx.静态方法
注意:
1. 静态方法中之所以不能实用实例变量和this、super,是因为在使用静态方法时可能还没创建实例呢
2. 静态方法重写不支持多态
3. 类属性即全局变量
四、语句块
1. static 代码块:属于类的,用来初始化类,给类的静态变量赋初值static{ 代码}
2. 语句块:属于某个实例的,每创建一个实例调用一次语句块
先语句块,后构造器
五、设计模式-单例模式
1. 好处:节省内存 提升效率
public class Singleton2 {
//
Method 1
private static Singleton2 st;
public static Singleton2 getInstance(){
if(st == null)
st = new Singleton2();
return st;
}
/* Method 2
* private static Singleton2 st;
private Singleton2(){}
static{
st = new Singleton2();
}
public static Singleton2 getInstance(){
return st;
} */
public static void main(String[] args){
Singleton2 st1 = Singleton2.getInstance();
Singleton2 st2 = Singleton2.getInstance();
System.out.println((st1==st2) ? "OK" : "NO");
}
}
2. 在哪些场合可以把构造方法声明为private 类型
2.1 在这个类中仅仅包含了供其它程序调用的静态方法,其它程序无须创建该类的
实例就能访问该类静态方法,
例如:
1). java.lang.Math (public final class Math{})
2). java.lang.System(public final class System)
2.2 这个类需要把构造自身实例的细节风封装起来,不允许其他程序通过new 语句创建这个类的实例,这个类向其它程序提供了获得自身实例的静态方法,这种方法称为静态工厂方法,比如单例设计模式
3. 如何禁止一个类被继承
1. 构造方法设计为private:既不允许创建实例,也不允许有子类
2. 类声明为final 类型:如果一个类允许其它程序用new 语句创建实例,但不允许拥有子类情况下

六、final关键字:
1.修饰谁
- 可以修饰类、方法、变量
1.1 final 修饰的类不可被继承,比如:String、System、Math 均被final 修饰
1.2 final 修饰的方法不可被覆盖
1.3 final 修饰的变量,必须显示赋一次值且变量值不可被改变
2.赋值
2.1 声明时直接赋值
2.2 构造方法中赋值
2.3 非static 代码块中赋值
3.常量 - static final 修饰的属性为常量
常量的赋值:
3.1 声明时直接赋值

3.2 static 代码块中
如何证明final 修饰的变量不一定是常量?
答:
public class Test {
private final int i1;
private static int i2=0;
public Test(){
i2++;
i1=i2;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("Test().i1 = "+new Test().i1);
System.out.println("Test().i1 = "+new Test().i1);
System.out.println("Test().i1 = "+new Test().i1);
}
}
结果:
Test().i1 = 1
Test().i1 = 2
Test().i1 = 3

七、抽象类
1. abstract 修饰的类为抽象类
2. 抽象类不能被实例化的原因:
1). 从语义上讲,抽象类表示从一些具体类中抽象出来的类型,例如苹果类、香蕉
类是具体类,而水果类则是抽象类,
在自然界并不存在水果类本身的实例,而只存在具体类的实例
2). 在语法上,抽象类中包含抽象方法,例如:
abstract class Base{
public void method1(){...}
public abstract void method2();
}
Base base = new Base(); //假定java 编译器没有报错
base.method1();
base.method2(); //运行时java 虚拟机无法执行这个方法,因为它是抽象方法,
没有方法体
3. 抽象类可以没有抽象方法,但有抽象方法的类一定是抽象类
4. 子类抽象为父类称为:泛化
5. 模板设计模式:所谓的模板即指抽象的父类,比如三个帐户类即用这种设计模式

八、接口
1. 接口和类是平级的,可以把它看成特殊格式的抽象类,但接口不是类
2. 接口的特殊性体现在
接口的属性默认:public、static、final ,且只能是这三个关键字修饰
接口的方法默认:public abstract , 且只能是这两个关键字修饰
接口没有构造方法,但抽象类有构造方法,因此必须对接口的属性直接赋值
接口与接口之间可以多继承
关键字不一样:interface (和class 同级的关键字有:interface and enum)
实现接口需要implements 关键字,且可以实现多个接口
接口的好处:
接口可以传递一些模块交互的信息,因无实现的代码,因此安全
接口可以定义一些规范,它是制定的标准,把服务的制定者和实现者分离开
注意:
abstract 不可以和private、final、static 中的任何一个一起出现
(static 修饰后,即使实现类后,调用的还是父类的,而父类方法没有实现,因此static 不支持方法多态)
接口最大的用处:在于降低系统的耦合性(可扩展性、可维护性)
高内聚:内聚是类和模块独立完成某一功能的能力
低耦合:耦合是类与类之间、模块与模块之间关联关系的复杂度
(内聚性越高、扩展和维护更方便)

九、Object类
Object 类是所有类的父类,它有一系列的方法,在此介绍三个
1.clone()方法
接口就是规范,因此如果要用clone()方法,需要实现Cloneable 接口,此接口没有方法
1.1 clone 方法的用法
1.1 实现Cloneable 接口
1.2 重写Object 中的clone()方法
1.2 浅克隆)
public class TestClone implements Cloneable{
private String name = new String("徐振跃");
private int a = 25;
/*
* 父类的clone()方法是protected 修饰的,通常情况是需要重写的
* public Object clone() throws CloneNotSupportedException{
return super.clone();
}
*/
public static void main(String[] args) {
TestClone tc = new TestClone();
TestClone tc2 = null;
try {
tc2 = (TestClone)tc.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(tc==tc2); //比较第一层
System.out.println(tc.name == tc2.name); //比较第二层
//如果深克隆每层都为不相等,即结果都为false
//如果浅克隆只有第一层相等,其它各层都不相等
}
}
1.3 深克隆
2.equals()
Object 预设的equals()本身是比较对象的内存地址是否相同,即“==”,因此需要重新定义equals()方法,以定义你自己的对象在什么条件下可视为相等的对象
特性:
自反性:a.equals(a)为true
对称性:...
传递性:...
一致性:a.equals(b)永远是同一个结果
对于任何非空引用值x,x.equals(null)都应返回false;
语法上equals()和hashCode()二者无关,但通常情况:
1. equals()为true,则hashCode()相同
2. equals()为false,则hashCode()不同
地址、equals()、hashCode()的区别:
地址:内存的东西
equals():判定内容是否相同
hashCode():可以通过它进行地址的映射
不能改变内存地址,可以改变映射内存地址的hashCode()

3.toString()
-用于返回一个对象的字符串表示
Object 的toString()预设会传回类别名称及16 进位制的编码内部实现hashCode()的方式:
getClass().getName()+"@"+Integer.toHexString(hashCode())
三种调用toString()的情况:
1. 类(对象).toString()--显示调用
2. print()/println()会自动调用toString()
3. 和字符串做链接(即+)的时候会自动调用toString()

十、基本类型的封装-封装类:
8 种基本类型都有对应的封装类
下面以Integer 类为例进行说明:
1.三角转换:
String
int
Integer
String->int: Integer.parseInt(str);
int -> String:i+"";
Integer->int: inte.intValue();
int->Integer: new Integer(int i)
String->Integer: new Integer(str)
Integer->String: toString()

2.Integer类其它方法:
参数也可其它的基本类型
static String toBinaryString(int i)
static String toHexString(int i)
static String toOctalString(int i)
3.自动装箱/自动解箱
- Integer 在jdk5.0 中的特性(包括非Boolean 类的包装类):
Integer i1 = 1; //自动装箱
Integer i2 = 1;
int i11 = i1; //自动解箱
System.out.println(i1==i2); //true 界限在-128~127
System.out.println(i1.equals(i2)); //true
3.1.当将Integer 换成Byte、Short、Long、Character 时同样i1==i2 也为true,但Float、
Double 不可以
3.2 自动装箱中的byte 池:当数字在byte 范围内时,会去byte 池中找对象,超过
范围则去堆中找
3.3 自动解箱失败情况:Integer i2=null;
int i3 = i2; //编译时通过,但运行时抛异常,即自动解箱失败

4.注意事项
1. 六个包装类Byte、Short、Integer、Long、Float、Double 都有一个共同的父类
java.lang.Number,且Number 类是一个抽象类,
2. Number 类内部有byteValue()、shortValue()、intValue()、longValue()、floatValue()、
doubleValue()六个抽象方法,因此可以使用更一般化的java.lang.Number 类别自动装箱,例:
Number number = 3.14f; .14f 会先被自动装箱为Float,然后指定给Number
3. 小心使用自动装箱和解箱
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值