本文是复习笔记,初学者若是不理解面向对象的概念能够看看个人另外一篇博客:http://www.javashuo.com/article/p-zjxmduaw-ht.htmlhtml
变量定义在栈中,而具体的对象数据则在堆区java
构造函数,构造器python
语法要求设计模式
1.函数名称与类名一致 2.不容许有返回值类型 3.不容许使用return语句返回数据
特色:安全
new 对象时会自动执行 1.能够重载多个构造方法 2.当咱们没有定义任何构造方法时,会自动生成无参的空构造方法 3.一旦咱们定义类构造方法,系统将不会自动生成
构造方法只能经过两种方式来调用:ide
1.在构造方法中可经过this去调用其余的构造方法 2.经过new 关键字 //在普通方法中也不能去掉用构造方法 public class Constructer { public Constructer(){ } public Constructer(String name){ this(); //调用空参数构造方法 } }
1.只能经过规定的接口(方法)访问内部数据函数
2.隐藏了内部实现细节,为了隔离复杂度,和提升安全性,提升了类内部的维护性性能
修改方法或属性的权限为private 私有化测试
为私有的属性提供对外开放(public)的setter 和getter方法;this
public class Test { private String name;//该属性被私有化 此时该属性尽在该类内部能够访问 public Test(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
包的本质是一个文件夹
当一个项目中出现大量的类是,维护性会下降,咱们能够采起分包的方式来管理 ,将相关的类放到同一个包中,方便管理维护代码,
采用域名倒叙,+模块名称+功能名称
全小写
import用于导入某个类
语法:
1.导入某个包下的某个类 import com.yh.package1.Cat;
2.导入某个包下的全部类 import com.yh.package2.*;
import com.yh.package1.Cat
com.yh.package1.Cat c1 = new com.yh.package1.Cat(); c1.show();
static修饰的成员称之为静态成员
特色:
1.可使用类名直接调用(固然对象也能够)
2.而且static修饰的成员属于类名称空间中,也就是说全部该类对象,共享该资源,相反的若是非static修饰的成员是每一个对象独有的,例如每一个人的name属性不一样;
3.静态成员的生命周期跟随的类,类加载时被加载,虚拟机结束时被销毁;
4.在静态方法中不可使用this关键字,由于static修饰的成员比对象先被加载
5.静态方法中只能访问静态成员
使用一对大括号产生一个代码块,固然了方法也是代码块
咱们还能够在类中直接使用{}来定义出一个构造代码快 像下面这样
class Person(){ { //构造代码块,会在建立类的时候先于构造函数执行,没建立一个对象就执行一次 } }
class Person{ void show(){ //方法体 { // 普通代码块 } //方法体 } }
在类中使用static来修饰的代码块就是静态代码块,其执行时机是在类被加载时,执行一次,后续不在执行,
何时使用?
当咱们须要在使用类以前作一些初始化操做时
问题?
1.代码块是不是局部做用域 ? 是的每一个代码块都是局部的
2.静态代码块中是否能够存在方法? 不能够局部代码块建立方法没有意义
静态代码块 -> 构造代码块 -> 构造方法
一个类和另外一个类之间的关系,是一种什么是什么的关系(A is aB)
如猪是动物,
好处:子类继承父类能够直接使用父类开放(非private)的已存在成员
extends关键字创建继承关系,一个类只能有一个父类
class Animal{ String name; } class Person extends Animal{ public void show(){ System.out.println(this.name);//直接访问父类成员 } }
override
当子类出现了与父类彻底一致(相同返回值类型,相同名称,相同参数列表)的方法时将产生覆盖
当父类的方法 没法直接知足需求时子类能够覆盖父类已有方法
也就是说若是子类想定义新的方法要么名称不一样,要么参数列表不一样
修饰符 | 本类 | 同包 | 子类 | 其余包 |
---|---|---|---|---|
public | yes | yes | yes | yes |
protected | yes | yes | yes | no |
default | yes | yes | no | no |
private | yes | no | no | no |
当子类覆盖了父类的方法时,按照顺序将优先执行子类中的方法,当咱们须要执行父类方法时
能够在子类中使用super关键字来调用父类的方法
class A{ public A(){ } public show(){ System.out.println("hello java!"); } } class B extends B{ public B(){ super().show(); } }
1.加载类(仅发生一次)
2.加载父类静态资源
3.加载子类静态资源
4.执行父类构造代码块
5.执行父类构造函数
6.执行子类构造代码块
7.执行子类构造函数
8.完成
this:
本类的,属性,方法,构造器
super:
父类的,属性,方法,构造器
注意:this和super不能同时出如今构造函数中
翻译为最终,能够修饰类,变量,方法
1.在继承关系中,被final修饰的方法没法被覆盖
2.final修饰变量时,就变成了常量,一旦初始化值不容许修改
3.final修饰类时,表示该类不能被继承
JDK1.5 推出
用于对方法或变量进行说明
源码注解尽在编译完成时自动去除,用于对元素进行标记,方便编译器识别,例如@override
编译时注解指的是编译成class后依然存在的注解
运行时注解指的是,会对程序逻辑产生影响的注解,例如autowrite,transaction等..
常见23中设计模式,及其分类;
某个类有且仅有一个实例,那ta就是单例类
1.将构造函数私有化 以禁止外界本身初始化
2.利用static仅加载一次的特性,建立一个静态的对象做为类的私有属性
3.提供访问这个静态对象的方法
1.饿汉式: 直接在声明static属性时建立对象 这种方法是线程安全
class SingleInstance{ private static SingleInstance obj = new SingleInstance(); private SingleInstance(){ //私有化的构造函数 } public SingleInstance getInstance(){ return obj; } }
2.懒汉式:在获取对象是若是发现对象为空才建立 这种方法是非线程安全
public class Emperor { //定义私有构造方法 private Emperor(){ System.out.println("create instance!"); } //定义私有静态类对象 private static Emperor obj = null; //定义公有静态方法返回类内的私有静态对象 public static Emperor get_instance(){ if(obj == null){ obj = new Emperor(); } return obj; } }
优势:
节省空间,提升性能
缺点:
扩展困难
当对象长期不使用,困难会被回收致使异常
使用场景:
当程序须要共享同一份对象的数据时
当每一个对象数据都相同时,则没有必要建立对个对象
当须要保证某些数据的一致性时,例如: 要生成惟一的id,若是每一个对象都有一份本身的生成方式则可能形成数据错误
多个不一样对象能够响应同一个方法产生各自不一样的行为
指的是在编译阶段就能识别具体要执行的方法是哪个,一般是方法重载,经过参数不一样决定调用哪一个方法
只有在运行时才能肯定到底调用哪一个方法
注意下面的内容都是针对运行时多态,是任何OOP语言的共同特性
1.必须具有继承关系
2.父类指针指向子类对象
ps:在python中没有这两个限制,python是动态类型,编译期间不会检查对象具体类型,更加灵活,可是也增长了风险
指的是用父类指针引用子类实例,会自动将子类转换为父类,转换后将隐藏子类特有的成员,只能使用父类中定义的方法和属性,
当明确某个对象就是某个子类对象时能够强制转换为子类,如此就能够从新访问子类中独有的成员
当不能明确对象是不是某个类型时可使用 instanceof
if(obj instanceof Objcet){ System.out.println("obj is ObjectClass instance"); }else{ System.out.println("obj not ObjectClass instance"); }
抽象类指的是类中包含抽象方法的类,
抽象方法指的是没有任何方法体的方法
使用abstract关键字类表示抽象方法 或抽象类
当父类须要规定子类应该具有某些方法,但父类自己不清楚方法具体如何实现时使用抽象类,
用于提早告诉子类,你应该具有哪些方法
存在抽象方法的类没法直接实例化产生对象,必须由子类继承并实现全部抽象方法才能实例化子类
如子类没有实现全部抽象方法,那么子类也只能做为抽象类
实例:
abstract class Person{ abstract public void show(); } class Student extends Person{ @Override public void show(){ System.out.println("show"); } }
1.若是设计子类的人清楚的知道本身应该作的事情时(方法),能够不用抽象类,抽象类本质就是限制子类必须怎么怎么滴
2.须要注意final 不能与 abstract 同时出现
接口是一组功能(方法)的定义
定义一组协议方法,让子类遵循协议中的要求去实现具体的操做,对于使用者而言,只须要掌握接口中定义的方法的使用便可,无需关心,具体是哪个类实现的,更不用关心是如何实现的, 这将类的设计者和类的使用者之间的耦合度大大的下降了,
interface Name { }
接口本质是一个类,可是与普通类有着众多区别
1.接口中的方法默认都是抽象的不能有方法体
2.接口中定义的变量默认都是静态常量
3.接口中的成员必然是public修饰的,即时没有明确声明
4.接口没法直接实例化
5.接口能够继承一个或多个其余接口
6,一个类能够同时实现多个接口
某些状况下,接口中声明了不少抽象方法,然而子类不须要实现所有,而是想仅实现部分须要的,这种状况在1.8以前是不容许的,除非把这个子类变成抽象的,这不够灵活;
案例:
package com.yh.src; interface HDMI { static int a = 0; // 上述代码等价于public static final int a = 0; //抽象方法 void generalMethod(); //上述代码等价于public void test(); //默认方法 子类可选重写 default void defaultMethod(){ System.out.println("默认的方法体"); } //静态方法 子类不可重写 static void staticMethod(){ System.out.println("静态方法体"); } } class AA implements HDMI { @Override public void generalMethod() { System.out.println("AA Implements generalMethod!"); HDMI.staticMethod();//静态方法只能有接口名称调用 } @Override public void defaultMethod() { //super.test1();//没法经过super调用接口中的默认方法 HDMI.super.defaultMethod();//须要使用接口名称.super来调用 } } public class InterfaceRunner { public static void main(String[] args) { AA a = new AA(); a.generalMethod(); a.defaultMethod();//调用未被重写的默认方法 //a.staticMethod();//没法直接调用接口中的静态方法 HDMI.staticMethod();//静态方法只能由接口名称调用 } }
接口名称.super.方法名称
如HDMI.super.defaultMethod();
PS:其实取消抽象方法和接口同样能够实现设计-使用松耦合,直接使用普通类做为父类,子类本身实现该实现的方法,固然了java为何占领企业开发也正是由于其严谨,标准规范,
你会发现,为了提升灵活性接口好像变得和抽象类很是类似,.......干脆像python同样别整这么多约束,,,
与普通类不一样的是一个类能够同时实现多个接口,增长了子类的扩展性
可是也带来了访问不肯定性,
interface IA{ default void test(){ System.out.println("IA test!"); } } interface IB{ default void test(){ System.out.println("IB test!"); } } //实现类直接编译失败, class IMA implements IA,IB{ }
//在子类中重写冲突的方法,便可 当须要调用默认方法时,使用`接口名称.super.xx`来调用 class IMA implements IA,IB{ @Override public void test() { IA.super.test(); IB.super.test(); } }
interface IA{ default void test(){ System.out.println("IA test!"); } } interface IB{ default void test(){ System.out.println("IB test!"); } } class P{ public void test(){ System.out.println("IB test!"); } } class IMA extends P implements IA,IB{ }
这种状况下不会出现问题,将直接调用父类中的方法
interface IA{ int a =10; int b =100; } interface IB{ int a =20; } class P{ int a = 20000; } class IMA extends P implements IA,IB{ public void func(){ System.out.println(a);//编译错误 System.out.println(IA.a);//使用接口名称来明确 System.out.println(super.a);//使super来指定访问父类 System.out.println(b);//不存在重复的时直接能够访问 } }
此时子类没法明确选择一个要访问的常量,必须使用接口名称来明确
要访问父类时使用super来明确
子类对象能够直接访问接口中没有冲突的静态变量,可是没法直接访问静态方法须要使用接口名称调用
当一个类定义在一个类的范围中,则这个类称之为内部类,与之对应的是包含这个内部类的外部类
实例:
class A{//外部类 class B{ //内部类 } }
public class InnerClass { public static void main(String[] args) { //实例化内部类方法1 A.B obj; //定义 obj = new A().new B(); //实例化内部类方法2 A aobj = new A(); obj = aobj.getInner(); //实例化内部类方法3 obj = aobj.new B(); } } class A{ public B getInner() { return new B(); } class B{ } }
public class InnerClass { public static void main(String[] args) { //实例化内部类方法1 A.B obj; //定义 obj = new A().new B();//实例化 obj.test();//调用方法访问外部类的成员 } } class A{ int inta = 100; int intb = 200; public B getInner() { return new B(); } class B{ int intb = 300; public void test(){ System.out.println(inta);//100 能够直接访问外部类成员 System.out.println(intb);//300 冲突时优先访问内部 System.out.println(A.this.intb);//200 冲突时指定访问外部 } } }
class A{ int inta = 100; int intb = 200; public void accessInner() { B b = new B();//实例化 b.test();//访问 } class B{ int intb = 300; public void test(){ System.out.println(inta); System.out.println(intb); System.out.println(A.this.intb); } } }
外部类访问内部类成员时须要先实例化内部类的对象,经过对象访问便可
注意:普通内部类中不能包含任何static修饰的成员
能够将内部类使用static修饰,此时他就是静态内部类
与普通内部类的不一样之处,与static修饰的其余成员有着相同的特征:
在类被加载时就一块儿加载,因此,能够直接实例化,不须要先实例化外部类;
静态内部类中的能够包含静态成员而且也能够直接调用(外部类.内部类.属性
);普通类中不能够有静态成员;
实例:
public class InnerClass2 { public static void main(String[] args) { System.out.println(OUT.IN.a);//直接访问静态内部类的静态成员 OUT.IN.test();//访问静态内部类方法 } } class OUT{ static int a = 10; String name = "jack"; static class IN{ static int a = 100; static public void test(){ System.out.println(a);//优先访问内部类 System.out.println(OUT.a);//指定访问外部类 System.out.println(new OUT().name);//访问外部非静态成员 } } }
定义在方法中的类称为局部内部类
意义不大..没啥用..略过了
class A{ public void test(){ class B{ //局部内部类 } } }
特色:不容许使用static修饰局部内部类,和其中的任何成员,要使用该类必须做为返回值return出去
字面意思就是没有名字的类
经过new 实例化接口或是抽象类,同时提供相应的方法实现
实例:
interface USB{ void open(); } class PC { public void working(){ //此处须要一个实现了USB接口的对象来完成操做 //咱们能够定义一个类实现USB接口先下面的A类同样 //而后实例化A对象来完成OPEN操做 new A().open(); //咱们也可使用匿名内部类的方式来简化操做 new USB(){ public void open(){ System.out.println("OPEN......"); } }.open; } } class A implements USB{ public void open(){ System.out.println("OPEN......"); } }
在上面的例子中咱们能够看出匿名内部类有如下优势:
代码更加紧凑
使用更便捷
固然匿名内部类的缺点也很明显:
1.临时须要某个接口或是抽象类的独享完成某个功能
2.当整个任务的部分代码已经完成,可是剩下一部分关键代码须要由使用这个功能的人来完成
案例:
PC类的working方法须要传入一个USB接口对象才能完成整个任务
interface USB{ void open(); } public class PC { public static void main(String[] args) { new PC().working(new AP());//之前的方式:定义类实现方法而后实例化 new PC().working(new USB() {//匿名内部类的方式:在当前位置完成上述所有操做 @Override public void open() { System.out.println("open on NonNameClass"); } }); } public void working(USB usb){ usb.open(); } } class AP implements USB{ public void open(){ System.out.println("OPEN......on AP"); } }
PS:我的以为匿名内部类+匿名对象其实 与OC中的block,python中的函数对象要完成的事情是同样的,即方法的使用者实现部分代码,而后做为参数传给某个方法(本质就是回调机制
),可是JAVA中定义方法必须借助类,因此才有了匿名内部类这么一说,归根结底是由于JAVA强制面向对象致使的;
补充:匿名内部类中可使用构造代码块