1.类和对象的基本概念 面向对象编程语言(OOP)是区分高级编程语言和中级的一项重要指标。与面向过程语言不同的是,面向对象语言所考虑的是如何对现实中的事物抽象成一个类来进行处理。其中类是对一群具有相同特征的事物的集合,而对象是指具有这些特性的个体,类强调的是整体,对象强调的是个体
类中最重要的是属性(也叫字段field)与方法,属性是对类的的描述,方法是对类属性的操作。按照闭包的程序设计原则,类中的属性应当私有,需要访问的时候对外暴露共有的方法。对外暴露的方法在Java中一般使用get和set方法。定义一个对象通常是使用类来new
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public class Main { public static void main (String[] args) { Person ming = new Person(); ming.setName("Xiao Ming" ); ming.setAge(12 ); System.out.println(ming.getName() + ", " + ming.getAge()); } }class Person { private String name; private int age; public String getName () { return this .name; } public void setName (String name) { this .name = name; } public int getAge () { return this .age; } public void setAge (int age) { if (age < 0 || age > 100 ) { throw new IllegalArgumentException("invalid age value" ); } this .age = age; } }
构造方法和toString方法 构造方法是特殊的一类方法,构造方法是方法名与类名相同的的方法。分为无参构造和有参构造。构造方法主要用于对类的初始化操作。当new一个对象时,会自动执行其构造方法,如果传递了参数会执行带参数的构造。
toString方法用来返回以一个字符串表示的对象值, @Override注解表示对方法的重写,通常情况下会对类的toString方法进行重写,以满足业务要求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class Main { public static void main (String[] args) { Person ming = new Person("小明" , 22 ); System.out.println(ming); } }class Person { private String name; private int age; public Person () { System.out.println("Person无参构造" ); } public Person (String name, int age) { this (); this .name = name; this .age = age; System.out.println("Person带参构造,name=" + name + ",age=" + age); } @Override public String toString () { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}' ; } }
this和super的区别 this表示的是当前对象,从本质上讲,this是一个指向本对象的指针。super表示对父类的引用。如果带有参数表示的是引用的是构造函数。new一个对象的时候会首先默认调用父类的构造方法,然后再调用自身的构造方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 public class ClassDemo { public static void main (String[] args) { Sun davie = new Sun(); davie.show(); Sun jack = new Sun(45 ); jack.show(); } }class Father { int age = 50 ; public Father () { System.out.println("Father无参构造" ); } public Father (int age) { this .age = age; System.out.println("Father有参构造,age=" + age); } }class Sun extends Father { int age = 20 ; public Sun () { System.out.println("Sun无参构造" ); } public Sun (int age) { super (age); this .age = age; System.out.println("Sun有参构造,age=" + age); } void show () { int age = 30 ; System.out.println(age); System.out.println(this .age); System.out.println(super .age); } }
静态变量和静态方法 Java中其他的字段和方法在实例化的时候都会创建一个独立的内存空间,而静态变量和方法拥有共享的静态变量区和静态方法区。所有的静态内容会在类加载的时候分配内存空间而不是对象创建的时候分配。静态资源可以直接通过类名来访问。
类的初始化次序:
(静态变量、静态初始化块)–>(变量、初始化块)–> 构造器;如果有父类,则顺序是:父类static方法 –> 子类static方法 –> 父类构造方法- -> 子类构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 public class Main { public static void main (String[] args) { Person person = new Person(); System.out.println(Person.info); } }class Person { String name = test(); int age; String sex; { System.out.println("我是普通代码块" ); } Person() { System.out.println("我是构造方法" ); } String test () { System.out.println("我是成员变量初始化" ); return "小明" ; } static String info = init(); static { System.out.println("我是静态代码块" ); } static String init () { System.out.println("我是静态变量初始化" ); return "test" ; } }
访问控制 Java中具有四种访问控制权限,四种访问控制权限可以作用与变量上,也可以作用与类上。需要额外注意的是一个类文件中只能有一个public类
当前类 同一个包下的类 不同包下的子类 不同包下的类 public ✅ ✅ ✅ ✅ protected ✅ ✅ ✅ ❌ 默认 ✅ ✅ ❌ ❌ private ✅ ❌ ❌ ❌
2.继承、多态、封装 继承、多态、封装是面向对象的最基本的三项特征。前面的例子中的闭包原则就是封装的重要特性,继承的例子也通过了super和this关键字进行了演示,需要注意的是Java语言是单继承的机制,即一个子类只能有一个父类。类定义的时候加final关键字表示该类不可以被继承。java中的所有类都继承自一个顶层类Object,Object类中提供了toSring,equals等方法。
封装示例:单例设计模式
1 2 3 4 5 6 7 8 9 10 11 public class Person { private String name; private int age; private String sex; private Person () {} public static Person getInstance () { return new Person(); } }
方法重写与重载 方法重写是子类与父类之间,一般用于扩展父类所拥有的方法。重载是在同一个类当中的,重载是指方法名字相同,而参数不同。返回类型可以相同也可以不同。是对方法参数和返回值的增强。方法的重写体现了类的多态性,另外父类可以初始化子类对象同样体现了多态性
区别点 重载方法 重写方法 参数列表 必须修改 一定不能修改 返回类型 可以修改 一定不能修改 异常 可以修改 可以减少或删除,一定不能抛出新的或者更广的异常 访问 可以修改 一定不能做更严格的限制(可以降低限制)
父类初始化子类对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Main { public static void main (String[] args) { Person p = new Student(); p.run(); } }class Person { public void run () { System.out.println("Person.run" ); } }class Student extends Person { @Override public void run () { System.out.println("Student.run" ); } }
抽象类 抽象类是对类的进一步抽象。通常来讲,一个类中定义了方法,但没有具体的执行代码,这个方法就是是抽象方法,而相对应的类称为抽象类。使用abstract关键字来声明。抽象类通常用于子类和父类之间。可以通过抽象类去引用具体的子类实例。而程序设计中,有面向抽象编程
上层代码只定义规范(例如:abstract class Person); 不需要子类就可以实现业务逻辑(正常编译); 具体的业务逻辑由不同的子类实现,调用者并不关心。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 public class Main { public static void main (String[] args) { Person student = new Student("张三" ,18 ,"男" ) { @Override public void exam () { super .exam(); } }; student.exam(); Person worker = new Worker("李四" ,28 ,"男" ); worker.exam(); } }abstract class Person { protected String name; protected int age; protected String sex; protected String profession; protected Person (String name, int age, String sex, String profession) { this .name = name; this .age = age; this .sex = sex; this .profession = profession; } public abstract void exam () ; }class Worker extends Person { public Worker (String name, int age, String sex) { super (name, age, sex, "工人" ); } @Override public void exam () { System.out.println("打工人,打工混" ); } }abstract class Student extends Person { public Student (String name, int age, String sex) { super (name, age, sex, "学生" ); } @Override public void exam () { System.out.println("DDL, DDL, DDL" ); } }
接口 接口是对抽象类的进一步抽象。如果一个抽象类中没有字段,所有方法都是抽象方法,那么就可以把他定义为接口。接口使用关键字interface。实现接口需要使用implements关键字。接口是可以进行多继承的。接口也是现在程序设计中最常用的方式。从java8开始,接口可以使用default关键字实现默认方法。接口不允许定义成员变量和成员方法,但可以定义静态变量和静态方法
abstract class interface 继承 只能extends一个class 可以implements多个interface 字段 可以定义实例字段 不能定义实例字段 抽象方法 可以定义抽象方法 可以定义抽象方法 非抽象方法 可以定义非抽象方法 可以定义default方法
接口实现类深拷贝案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public class Main { public static void main (String[] args) throws CloneNotSupportedException { Student student = new Student("小明" , 18 , "男" ); Student clone = (Student) student.clone(); System.out.println(student); System.out.println(clone); System.out.println(student == clone); student.stu(); Study.test(); System.out.println(Study.pi); } }abstract class Person { protected String name; protected int age; protected String sex; protected String profession; protected Person (String name, int age, String sex, String profession) { this .name = name; this .age = age; this .sex = sex; this .profession = profession; } }class Student extends Person implements Study , Cloneable { public Student (String name, int age, String sex) { super (name, age, sex, "学生" ); } @Override public Object clone () throws CloneNotSupportedException { return super .clone(); } @Override public void study () { System.out.println("我会学习!" ); } }interface Study { public static final float pi = 3.14f ; static void test () { System.out.println("我是静态方法" ); } void study () ; default void stu () { System.out.println("我是默认实现" ); } }
枚举类 枚举类通常是用来记录状态信息,例如星期,颜色这类的信息。枚举类使用的关键字是enum。枚举常量本来担忧类型的信息,编译器是可以检查类型的错误。不同的枚举不能相互比较或赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public class Main { public static void main (String[] args) throws CloneNotSupportedException { Student student = new Student("小明" , 18 , "男" ); student.setStatus(Status.RUNNING); System.out.println(student.getStatus().getName()); } }abstract class Person { protected String name; protected int age; protected String sex; protected String profession; protected Person (String name, int age, String sex) { this .name = name; this .age = age; this .sex = sex; } }enum Status { RUNNING("跑步" ), STUDY("学习" ), SLEEP("睡觉" ); private final String name; Status(String name) { this .name = name; } public String getName () { return name; } }class Student extends Person implements Study { private Status status; protected Student (String name, int age, String sex) { super (name, age, sex); } public Status getStatus () { return status; } public void setStatus (Status status) { this .status = status; } @Override public void study () { System.out.println("我会学习!" ); } }interface Study { void study () ; }