面向对象开发的优势
稳定性可扩展性可重用性成员属性就算没有 赋值,也是有 默认初始值的. 如下:
字符串类型的默认初始值为 null
整型的默认初始值为 0
浮点型的默认初始值为 0.0
具体如下:
实例化对象的过程可以分为两部分
声明对象 Cat one;实例化对象 new Cat();构造方法
构造方法与类同名且没有返回值! 必须和类名一样!!构造方法的语句格式构造方法 只能 在对象实例化的时候调用当没有指定构造方法时, 系统会自动添加无参的构造方法当有指定构造方法,无论是有参,无参的构造方法,都不会自动添加无参的构造方法一个类中可以有多个构造方法实例化代码 简化如下
Cat one = new Cat("花花", 2, 1000, "英国短毛猫");上述第8条的带参构造函数中, 我们用了 this. 代表的当前对象(谁调用它就是谁).
this的使用
调用成员属性(同一个类中的),解决成员属性和局部变量同名冲突调用成员方法(同一个类中的)调用重载的构造方法 (例如在 有参构造中,调用 this() 表示调用无参构造方法) 注意: 通过this()调用构造方法,必须放在方法体的第一行!特点:
只能通过规定的方法访问数据隐藏类的实例细节,方便修改和实现实现步骤
修改属性的可见性, 访问修饰符修改为 private (私有,只允许在类内访问).创建 getter/setter 方法, 访问修饰符设置为 public, 用于属性的读写.在 getter/setter 方法中加入属性控制语句. public class Cat{ ... // 修改属性的可见性,修改为 私有 private, 限定只能在 当前类中访问,类外不允许访问! private String name; // 设置共有的 get/set 方法,供 外部调用! // 在 get/set方法中可以添加 属性的限定 public void setName(String name){ // 可以添加限制的代码 /* if( name == ''){ System.out.println("姓名不能为空!"); } */ this.name = name; } public String getName(){ // 可以添加限制的代码 /* return "小猫的名字为:" + this.name; */ return this.name; } ... }调用时代码如下
public class CatTest{ public static void main(String[] args){ Cat one = new Cat(); one.setName("凡凡"); ... System.out.println("昵称: " + one.getName()); ... } } eclipse 中快捷添加 getter/setter方法: 鼠标将光标点击到 合适位置,然后右键,Source / Generate Getter and Setter … 即可选择添加.注意: 如果使用了 getter/setter 方法, 那么在有参构造方法中, 赋值的话, 也推荐用 setter 方法.语法
package 包名;例: package com.imooc.animal;注意:
必须放在java源文件的第一行一个Java源文件中只能有一个 package 语句包名全部英文小写命名方式: 域名倒序+模块+功能语法:
import 包名.类名;例: 导入包中全部类: import com.imooc.*例: 导入包中指定类: import com.imooc.animal.Cat;实例演示如下: Test.java 中调用 Cat, 那么如何指定是 哪个 Cat呢?
解决方法
导包, 通过 import 导入所有类,如下代码所示 package com.imooc.newtest; import com.imooc.animal.*; //加载 com.imooc.animal 下面的所有类 public class Test { public static void main(String[] args) { Cat cat = new Cat(); CatTest test = new CatTest(); } } 也是导包, 通过 import 导入包下的特定类 package com.imooc.newtest; import com.imooc.animal.Cat; //加载 com.imooc.animal 下面的 Cat 类 public class Test { public static void main(String[] args) { Cat cat = new Cat(); } } 直接在程序中, 直接加载 com.imooc.animal.Cat 这样的方式 package com.imooc.newtest; public class Test { public static void main(String[] args) { com.imooc.animal.Cat cat = new com.imooc.animal.Cat(); } }如果 想同时引用这2个Cat, 注意,要用如下写法:
package com.imooc.newtest; import com.imooc.animal.Cat; import com.imooc.mechanics.*; //上面有 Cat了,这里只能这样写 public class Test { public static void main(String[] args) { Cat cat = new Cat(); com.imooc.mechanics.Cat two = new com.imooc.mechanics.Cat(); } }如上, 第二个 Cat, 就必须用 包名这样的形式来区别开.
static 可以加在 成员属性和成员方法前. 意义如下:
static + 成员属性 就变成了 静态属性/类属性 (所有对象都共享)static + 成员方法 就变成了 静态方法/类方法 (所有对象都共享)static 特点:
类对象共享类加载时产生,销毁时释放,生命周期长静态成员访问方式有2种:
对象.成员类.成员类方法访问和静态成员访问的方式类似,也是2种
对象.成员方法()类.成员方法() 推荐这种方式!静态方法(类方法)书写的时候,也有地方需要注意:
在成员方法中, 是可以直接访问类的静态成员的在 静态方法(类方法)中 不能直接访问同一个类中的 非静态成员(属性+方法), 只能直接调用 同一个类 中的静态成员(属性+方法).静态方法(类方法) 中,不能使用 this.在静态方法中,如果想使用非静态成员,可以实例化一个对象,然后通过对象去调用非静态成员.特点:
利于代码复用缩短开发周期继承:
一种类与类之间的关系使用已存在的类的定义作为基础建立新类新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择地继承父类父类(超类/基类) — 子类(派生类)继承的关系:
满足 “A is a B” 的关系就可以形成继承关系语法规则
返回值类型方法名参数类型,顺序,个数以上3点,必须和 父类 继承的方法相同.
方法重载:
同一个类中方法名相同,参数列表不同(参数顺序,个数,类型)方法返回值,访问修饰符任意与方法的参数名无关方法重写:
有继承关系的子类中方法名相同,参数列表相同(参数顺序,个数,类型),方法返回值可以允许是子类类型访问修饰符, 访问范围需要大于等于父类的访问范围与方法的参数名无关访问修饰符
私有的: private 只允许在本类中进行访问默认 允许在当前类,同包子类/非子类可以访问,但跨包子类/非子类都不允许访问.受保护的: protected 允许在当前类,同包子类/非子类,跨包子类可以访问! 但跨包非子类不允许.公有的: public 允许在任意位置访问访问范围
代表父类引用
访问父类成员方法 super.print()访问父类属性 super.name访问父类构造方法 super()this: 当前类对象的引用
访问当前类的成员方法访问当前类的成员属性访问当前类的构造方法不能在静态方法中使用用于 调用构造方法时,必须放在有效代码第一行super: 父类对象的引用
访问父类的成员方法访问父类的成员属性访问父类的构造方法不能在静态方法中使用使用 super 调用父类指定构造方法时, 必须在子类构造方法的第一行 this() 和 super() 必须在子类的有效代码第一行,是不允许同时出现的.Object 中常见的2个方法如下:
equals 测试
继承 Object 中的 equals 方法时, 比较的是两个引用是否指向同一个对象子类可以通过重写 equals 方法的形式,改变比较的内容toString 测试
输出对象名时, 默认会直接调用类中的 toString 方法继承 Object 中的 toString 方法时,输出对象的字符串表现形式: 类型信息+@+地址信息子类可以通过重写 toString 方法的形式,改变输出的内容以及表现形式注意: 放在 成员属性前,如果定义的时候没有赋值,那么 只能在 构造方法和构造代码块中赋值!!!
放在 引用类型前的时候, 实例化之后就不允许指向另外一个对象. 但是这个对象里面的属性值是可以修改的.final 不能放在构造方法前.可以配合 static 一起使用. 表示全局不允许被修改的静态属性.按照运行机制分类
源码注解编译时注解运行时注解按照来源分类
来自JDK的注解来自第三方的注解我们自己定义的注解创建型模式
工厂方法模式创建者模式抽象工厂模式原型模式单例模式结构型模式
桥接模式代理模式享元模式外观模式装饰器模式组合模式适配器模式行为型模式
备忘录模式
解释器模式
命名模式
中介者模式
观察者模式
策略模式
状态模式
模板方法模式
访问者模式
迭代子模式
责任链模式
设计模式是基于场景的解决方案
目的
使得类的一个对象成为该类系统中的唯一实例定义
一个类有且仅有一个实例,并且自动实例化向整个系统提供要点
某个类只能有一个实例必须自动创建实例必须自行向整个系统提供这个实例实现
只提供私有的构造方法含有一个该类的静态私有对象提供一个静态的公有方法用来创建,获取静态私有对象实现方案
饿汉式: 对象创建过程中实例化懒汉式: 静态公有方法中实例化懒汉式存在线程风险
同步锁双重校验锁静态内部类枚举单例模式优点
在内存中只有一个对象,节省内存空间避免频繁的创建销毁对象,提高性能避免对共享资源的多重占用单例模式缺点
扩展比较困难如果实例化后的对象长期不利用,系统将默认为垃圾进行回收,造成对象状态丢失使用场景
创建对象时占用资源过多,但同时又需要用到该类对象对系统内资源要求统一读写,如读写配置信息当多个实例存在可能引起程序逻辑错误,如号码生成器多态: 意味着允许不同类的对象对同一个消息做出不同的响应.
编译时多态: 设计时多态,通过 方法重载 完成.
运行时多态: 程序运行时动态决定调用哪个方法. (大多数的多态都是运行时多态)
必要条件
满足继承关系父类引用指向子类对象应用场景
某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法.public abstract void eat();
抽象类/抽象方法 使用规则
abstract 定义抽象类抽象类不能直接实例化,只能被继承,可以通过向上转型完成对象实例abstract 定义抽象方法,不需要具体的实现包含抽象方法的类,一定是抽象类抽象类中可以没用抽象方法static / final / private 不能与 abstract 并存定义接口
package com.imooc.tel; /** * 具有照相能力的接口 * * @author zhangqiang * */ public interface IPhoto { // 具有拍照的能力, public 可以省略 public void photo(); }实现接口
关键字: implements package com.imooc.tel; public class Camera implements IPhoto { @Override public void photo() { System.out.println("相机可以拍照"); } }如何调用
public class FourthPhone extends ThirdPhone implements IPhoto, INet {} //============== IPhoto ip = new FourthPhone(); ip.photo();接口定义了某一批类所需要遵守的规范
接口不关心这些类的内部数据,也不关心这些类里方法的实现细节,它只规定这些类里必须提供某些方法.
接口中抽象方法可以不写 abstract 关键字
访问修饰符默认 public ,可以不写
当类实现接口时,需要去实现接口中的所有抽象方法,否则需要将该类设置为抽象类
接口中 定义常量
package com.imooc.tel; //接口访问修饰符: public 或者 不写为默认的. public interface INet { // public static final int TEMP = 20; //接口中可以包含常量,默认 public static final // 所以可以直接写 int TEMP = 20; }访问 接口中的常量
INet.TEMP 接口名.常量名
或者用如下访问:
INet net = new SmartWatch(); System.out.println(net.TEMP);
**jdk1.8之后,新增 默认方法. **
方法前 加上 default, 意思为默认方法, 这个方法可不强制实现. package com.imooc.tel; //接口访问修饰符: public 或者 不写为默认的. public interface INet { // default: 默认方法,可以带方法体 jdk1.8后新增 // 可以在实现类中重写,并可以通过接口的引用调用 default void connection() { System.out.println("我是接口中的默认链接"); } }jdk1.8之后,新增 静态方法
package com.imooc.tel; //接口访问修饰符: public 或者 不写为默认的. public interface INet { // static: 静态方法, 可以带方法体 jdk1.8后新增 // 不可以在实现类中重写,可以在接口名中调用 static void stop() { System.out.println("我是接口中的静态方法"); } } 调用静态方法接口名.静态方法
接口中的默认方法,在实现类中是可以重写的
@Override public void connection() { // TODO Auto-generated method stub INet.super.connection(); }接口中的静态方法,在实现类中是无法重写的,可以用过接口名调用
调用
package com.imooc.test; public class Demo implements ISon { @Override public void say() { // IFather 接口中定义的方法 } @Override public void run() { // ISon 接口中定义的方法 } @Override public void fly() { // IFather2 接口中定义的方法 } }接口可以继承多个接口,那么多个父接口中如果有同名的默认方法,该怎么处理?
在自己的接口中,重写这个方法,即可解决!内部类的优势
内部类提供了更好的封装, 可以把内部类隐藏在外部类之内, 不允许同一个包中的其他类访问该类, 更好的实现了信息隐藏.内部类的分类
成员内部类静态内部类方法内部类匿名内部类定义内部类
package com.imooc.people; //外部类 public class Person { int age; public Heart getHeart() { return new Heart(); } // 成员内部类 class Heart { public String beat() { return "心脏在跳动"; } } }调用内部类
方法1: new 外部类().new 内部类()Person.Heart myHeart = new Person().new Heart();
外部类对象.new 内部类Person.Heart myHeart1 = lili.new Heart();
外部类对象.获取方法()Person.Heart myHeart2 = lili.getHeart();
package com.imooc.people; public class PeopleTest { public static void main(String[] args) { Person lili = new Person(); lili.age = 12; // 获取内部类对象实例: // 方法1: new 外部类().new 内部类() Person.Heart myHeart = new Person().new Heart(); System.out.println(myHeart.beat()); // 方法2: 外部类对象.new 内部类 Person.Heart myHeart1 = lili.new Heart(); System.out.println(myHeart1.beat()); // 方法3: 外部类对象.获取方法 Person.Heart myHeart2 = lili.getHeart(); System.out.println(myHeart2.beat()); } }成员内部类
内部类在外部使用时,无法直接实例化,需要借由外部类信息才能实现实例化.内部类的访问修饰符,可以任意,但是访问范围会受到影响.内部类可以直接使用外部类的成员信息(成员属性和成员方法)如果内部类和外部类,有相同的成员属性,那么内部类中就优先调用内部类中的.如果内部类和外部类,有相同的成员属性, 这时候内部类中优先调用的是内部类中定义的,但是如果想调用外部的,则可以用 外部类.this.成员的方式,访问外部类中同名的信息,例如 Person.this.age.外部类访问内部类信息,需要通过内部类实例,无法直接访问内部类编译后 .class 文件命名: 外部类$内部类.class内部类中是否可以包含与外部类相同签名的方法?
内部类中可以有和外部类的同名方法,在内部类中调用的时候,会优先调用内部类中的方法.如果在内部类有和外部类的同名方法, 要求使用外部类的, 要使用 外部类.this.成员方法()如何调用 静态内部类
静态内部类对象实例时,可以不依赖外部类对象 // 获取静态内部类对象实例 Person.Heart myHeart = new Person.Heart(); System.out.println(myHeart.beat()); 可以通过 外部类.内部类静态成员 的方式,访问内部类中的静态成员Person.Heart.say();
当内部类属性与外部类属性同名时, 默认直接调用内部类中的成员, 如果需要访问外部类中的静态属性,则可以通过 外部类.属性 的方式;如果需要访问外部类中的非静态属性, 则可以通过 new 外部类().属性 的方式.方法内部类
定义在方法内部,作用范围也在方法内和方法内部成员使用规则一样,class前面不可以添加 public, private, protected, static.类中不能包含静态成员(静态属性和静态方法)类中可以包含 final, abstract修饰的成员 package com.imooc.people; //外部类 public class Person { public int age; public Object getHeart() { // 方法内部类 class Heart { public int age = 1; int temp = 22; public void say() { System.out.println("hello"); } public String beat() { new Person().eat(); return new Person().age + "岁的心脏在跳动"; } } return new Heart().beat(); //调用一个具体的方法 } public void eat() { System.out.println("人会吃东西"); } }如何调用 方法内部类
package com.imooc.people; public class PeopleTest { public static void main(String[] args) { Person lili = new Person(); lili.age = 12; System.out.println(lili.getHeart()); } }适用场景
只用到类的一个实例类在定义后马上用到给类命名并不会导致代码更容易被理解匿名内部类
匿名内部类没有类型名称, 实例对象名称编译后的文件命名: 外部类$数字.class无法使用 private, public, protected, abstract, static因为没有名字, 所以匿名内部类无法编写 构造方法. 可以添加构造代码块.不能出现静态成员(属性和方法).匿名内部类可以实现接口也可以继承父类,但是不可兼得使用举例
定义父类 package com.imooc.anonymous; public abstract class Person { private String name; public Person() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public abstract void read(); } 匿名内部类的使用 package com.imooc.test; import com.imooc.anonymous.Person; public class PersonTest { // 根据传入的不同的人的类型,调用对应的read方法 public void getRead(Person person) { person.read(); } public static void main(String[] args) { PersonTest test = new PersonTest(); // 匿名内部类的使用 test.getRead(new Person() { @Override public void read() { System.out.println("男生喜欢看科幻类书籍"); } }); // 匿名内部类的使用 test.getRead(new Person() { @Override public void read() { System.out.println("女生喜欢看言情小说"); } }); } }