Java三大特征:封装、继承、多态
高内聚,低耦合:类的内部数据数据操作自己完成,不允许外部干涉;尽量暴露少量方法给外部使用
属性私有,get/set
封装的意义:
1、提高程序的安全性,保护数据
2、隐藏代码的实现细节
3、统一接口
4、系统的可维护性增加
Student类:
package oop.Demo03; //类 //封装一般是对于属性来的,很少封装方法 //private:私有 public class Student { //属性私有 private String name;//名字 private int id;//学号 private char sex;//性别 private int age; //提供一些可以操作这些属性的方法,提供一些public的get、set方法 //get 获得这个数据 (驼峰命名) public String getName(){ return this.name; } //set 给这个数据设置值 public void setName(String name){ this.name=name; } public void setAge(int age){//定义合理性 if(age>120||age<0) this.age=3; else{ this.age=age; } } public int getAge(){ return this.age; } //学习() //睡觉() }
Application类:
package oop; import oop.Demo03.Student; public class Application { public static void main(String[] args) { Student s1=new Student(); // s1.name = 不再能通过.操作符直接使用这些属性 s1.setName("张三"); System.out.println(s1.getName());//张三 s1.setAge(999); System.out.println(s1.getAge());//3 } }
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模
关键字:extends——扩展,子类(派生类)是父类的继承(基类),子类和父类之间从意义上将具有”is a“的关系
Java中只有单继承没有多继承,一个儿子只有一个爸爸,一个爸爸可以有多个儿子
除继承以外,类与类之间的关系还有依赖、组合、聚合等
子类继承了父类就会拥有父类的全部方法!(public)
私有的东西(private)无法被继承
在java中,所有的类都默认直接或者间接地继承object类
super注意点:
super();
1、super调用父类的构造方法,必须在构造方法的第一个
2、super只能和初夏安在子类的方法或者构造方法中
3、super和this不能同时调用构造方法
super和this的区别
this("hello");
代表的对象不同:
this:本身调用这个函数
super: 代表父类对象的引用
前提不同:
this:没有继承也可以使用
super:只能在继承条件下才可以使用
构造方法不同:
this():本类的构造
super():父类的构造
父类:
package oop.Demo04; // 人 :父类 //public //protected //default 默认 //private public class Person { public Person(){ System.out.println("Person无参执行了"); } protected String name="zhangsan"; public void print(){ System.out.println("Person"); } }
子类:
package oop.Demo04; //学生 is 人 :派生类、子类 public class Student extends Person{ public Student(){ //隐藏代码:调用了父类的无参构造:super(); super();//调用父类的构造器,必须在子类构造器的第一行 //this("hello"); System.out.println("Student无参构造执行了"); } public Student(String name) { this.name=name; } private String name="zhangwu"; public void print(){ System.out.println("Student"); } public void test1(){ print();//Student this.print();//Student super.print();//Person } public void test(String name){ System.out.println(name);//张五 System.out.println(this.name);//zhangwu System.out.println(super.name);//父类中的zhangsan } }
应用:
package oop; import oop.Demo04.Person; import oop.Demo04.Student; public class Application { public static void main(String[] args) { Student student=new Student(); // student.test("张五"); // student.test1(); // Student s1=new Student(); // s1.say();//说了一句话 // //System.out.println(s1.money);//报错 // Person person=new Person(); } }
重写都是方法的重写,与属性无关
父类:
package oop.Demo04; //重写都是方法的重写,与属性无关 public class B { public void test(){ System.out.println("B=>test()"); } }
子类:
package oop.Demo04; public class A extends B{ public void test(){ //super.test(); System.out.println("A=>test()"); } }
应用:
package oop; import oop.Demo04.B; import oop.Demo04.A; public class Application { public static void main(String[] args) { //方法的调用之和左边,定义的数据类型有关 A a = new A(); a.test();//A //父类的引用(b)指向了子类(A) B b = new A();//子类重写了父类的方法 b.test();//A } }
结果:
静态方法和非静态方法区别很大:
如果方法改成静态的:(就不是重写了)
package oop.Demo04; //重写都是方法的重写,与属性无关 public class B { public static void test(){ System.out.println("B=>test()"); } }
package oop.Demo04; public class A extends B{ public static void test(){ //super.test(); System.out.println("A=>test()"); } }
package oop; import oop.Demo04.B; import oop.Demo04.A; public class Application { public static void main(String[] args) { //方法的调用之和左边,定义的数据类型有关 A a = new A(); a.test();//A //父类的引用(b)指向了子类(A) B b = new A();//子类重写了父类的方法 b.test();//B } }
结果:
是不是重写可以看左边蓝色圆圈箭头,是重写才有,静态方法没有,改成私有也没有:
改成私有:
总结:
重写需要有继承关系,而且是子类重写父类的方法!
1、方法名必须相同
2、参数列表必须相同(区分于重载,重载是当前方法,且参数列表不同)
3、修饰符:范围可以扩大,但不能缩小 public>protected>default>private
4、区分于抛出异常:范围可以被缩小,但不能扩大。 ClassNotFoundExcetion -->Excetion(大)
重写就是子类的方法和父类必须相同,方法体不同
为什么要重写:
1、父类的功能,子类不一定需要,或者不一定满足
快捷键:Alt+Insert : override
instanceof (类型转换) 引用类型,判断一个对象是什么类型
父类:
package oop.Demo04; public class Person { }
子类1:
package oop.Demo04; public class Student extends Person{ }
子类2:
package oop.Demo04; public class Teacher extends Person{ }
应用:
package oop; import oop.Demo04.*; public class Application { public static void main(String[] args) { //Object>String //Object>Person>Teacher //Object>Person>Student Object object = new Student(); //System.out.println(X instanceof Y);//能不能编译成功,取决于X与Y有没有父子关系! System.out.println(object instanceof Student);//true System.out.println(object instanceof Person);//true System.out.println(object instanceof Object);//true System.out.println(object instanceof Teacher);//false System.out.println(object instanceof String);//false System.out.println("================"); Person person = new Student(); System.out.println(person instanceof Student);//true System.out.println(person instanceof Person);//true System.out.println(person instanceof Object);//true System.out.println(person instanceof Teacher);//false // System.out.println(person instanceof String);//编译报错,平级不能比较 System.out.println("================"); Student student = new Student(); System.out.println(student instanceof Student);//true System.out.println(student instanceof Person);//true System.out.println(student instanceof Object);//true // System.out.println(student instanceof Teacher);//编译报错,平级不能比较 } }
1、父类引用指向子类对象
2、把子类转换为父类(向上转型,低转高),直接转
3、把父类转换为子类(向下转型,高转低),需要强制转换
4、方便方法的调用,减少重复代码
抽象的编程思想:封装、继承、多态!抽象类:接口
父子关系和上文一样:
package oop; import oop.Demo04.*; public class Application { public static void main(String[] args) { //类型之间的转化:父|子 //高 低 Person obj = new Student(); // student.go();//不能执行 //student将这个对象转换为Student类型,就可以使用Student类型的方法了 //高转低强制转换 Student student = (Student) obj; student.go(); ((Student) obj).go(); //子类转为父类,可能丢失自己本来的一些方法 Student student1 = new Student(); student1.go(); Person person = student;//低转高直接转换 } }
对类来说静态变量在内存中只有一个,它能被类的所有实例共享
在类中,静态方法可以直接调用静态方法,但不能调用非静态方法
非静态方法可以调用静态方法里的所有东西
package oop.Demo05; //static public class Student { private static int age;//静态变量,多线程会使用 private double score;//非静态变量 public void run(){ go();//非静态方法可以调用静态方法里的所有东西 } public static void go(){ } public static void main(String[] args) { Student s1= new Student();//对类来说静态变量在内存中只有一个,它能被类的所有实例共享 System.out.println(Student.age);//0//静态变量推荐使用类名访问 // System.out.println(Student.score);//无法编译,非静态字段不能这么用 System.out.println(s1.age);//0 System.out.println(s1.score);//0.0 Student.go(); go();//在类中,静态方法可以直接调用静态方法,但不能调用非静态方法 // Student.run();//编译不成功 } }
静态代码块:
package oop.Demo05; public class Person { { //代码块(匿名代码块),作用:赋初始值 //没有名字,无法调用,类加载一次运行一次 System.out.println("匿名代码块"); } static{ System.out.println("静态代码块"); //静态代码块,类一加载直接执行,永久只执行一次 } public Person() { System.out.println("构造方法"); } public static void main(String[] args) { Person person1 = new Person(); System.out.println("============="); Person person2 = new Person(); } }
结果:
被final修饰的类不能被继承:
public final class Person { } public class Student extends Person{ }
关键字:abstract
public abstract class Action
抽象的抽象:约束
抽象类的所有方法,由继承了它的子类,都必须实现它的方法
抽象类的特点:
1、不能new这个抽象类,只能靠子类去实现它:约束
2、有抽象方法的类一定是抽象类,但抽象类里可以写普通方法
抽象类不能new,那它有构造器吗?
抽象类存在的意义是什么?
比如创建游戏中的角色,每个角色非常复杂,反复创建非常麻烦,抽象共有属性,修改各自方法就行。可以节省代码,提高效率
抽象类:
package oop.Demo06; //abstract 抽象类:类 只能单继承 extends:单继承(只能继承一个类) 接口可以实现多继承 public abstract class Action { //约束:有人帮我们实现 //abstract 抽象方法,只有方法名字,没有实现 public abstract void doSomething(); public void hello(){ System.out.println("hello"); } }
抽象类的子类:
package oop.Demo06; //抽象类的所有方法,由继承了它的子类,都必须实现它的方法 public class A extends Action{ @Override public void doSomething() { } }
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!自己无法写方法。专业的约束!约束和实现分离:面向接口编程
接口就是规范,定义的是一组规则,本质是契约
关键字:interface
public interface UserService
软件IDEA中普通类、抽象类和接口在图标上的的区别:
接口的作用:
1、是一种约束,可以定义一些方法,让不同的人实现
2、接口中的所有方法都是 public abstract,所有属性都是public static final
3、接口不能被实例化,接口不是类,接口中没有构造方法
4、类可以实现接口 关键字:implements 接口(可以实现伪多继承)
5、实现了接口的类,就需要重写接口中的所有方法
接口1:
package oop.Demo07; //interface 定义的关键字,接口都需要有实现类 public interface UserService { //接口中的所有定义的方法其实都是抽象的public abstract public abstract void run(); //接口中的所有定义的属性都是常量public static final(一般不会在接口里定义常量) public static final int age = 99; void add(String name); void delete(String name); void update(String name); void query(String name); }
接口2:
package oop.Demo07; public interface TimeService { void time(); }
应用1:
package oop.Demo07; //抽象类:extends //类可以实现接口 关键字:implements 接口 //实现了接口的类,就需要重写接口中的方法 //多继承:利用接口实现多继承 public class UserServiceImpl implements UserService,TimeService{ @Override public void run() { } @Override public void add(String name) { } @Override public void delete(String name) { } @Override public void update(String name) { } @Override public void query(String name) { } @Override public void time() { } }
在A类中定义B类,B类相对于A类就是内部类
使用:通过外部类来实例化内部类
一个java文件中可以有多个class类,但只能有一个public class
例1:
内部类:
package oop.Demo08; public class Outer { private int id; public void out() { System.out.println("这是外部类的方法"); } public void method(){ class Inner2{//局部内部类,类似函数里的局部变量 public void in(){//内部类里的方法 } } } public class Inner {//如果这里是public static class // 那下面getID就不行了,除非把id也改成static public void in() { System.out.println("这是内部类的方法"); } //内部类可以 获得外部类的私有属性 public void getID() { System.out.println(id); } } }
应用:
package oop; import oop.Demo04.*; import oop.Demo08.Outer; public class Application { public static void main(String[] args) { //new Outer outer = new Outer(); //通过外部类来实例化内部类 Outer.Inner inner = outer.new Inner(); inner.in(); } }
例2:
(一般不这么用)
package oop.Demo08; public class Test { public static void main(String[] args) { Apple apple = new Apple(); //没有名字初始化类——匿名对象的使用,不用将实例保存到变量中 new Apple().eat(); UserService userService = new UserService(){ public void hello(){ } }; } } class Apple{ public void eat(){ System.out.println("1"); } } interface UserService{//接口 void hello(); }