1.封装
封装是把过程和数据包围起来,对数据的访问只能通过指定的方式。
高内聚,低耦合
高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
低耦合:只有少量的方法给外部使用。
属性私有 get 和 set 方法,在set 方法中可以设置一些判断条件,来确保数据的正确性。
封装的作用:
1.提高程序的安全性,保护数据
2.隐藏代码的实现细节
3.统一用户的调用接口,所有的方法都是get() 和set()
4.系统可维护性增强了
5.便于调用者的调用
封装的步骤:
1.使用private修饰需要封装的成员变量。
2.提供一个公开的方法设置或者访问私有的属性 get 和set 方法来设置和访问。
3.可以在set方法里设置条件,进行安全性的判断。
一、对象能在外部直接访问的:对象.属性 或者 对象.方法
public class Student{ public String name; public void println(){ System.out.println(this.name); } } public class Test{ public static void main(String[] args){ Student s = new Student(); s.name = "tom";//对象.属性 直接赋值 } }
二、类中不会把类暴露在外部,而使用私有private关键字把数据隐藏起来,通过get()和set()两种方法来获取。
public class Student{ private String name; public void setName(String name){//set负责给属性赋值 this.name = name; } public String getName(){//get负责返回属性的值 return this.name; } } public class Test{ public static void main(String[] args){ Student s = new Student(); s.setName("tom");//只能通过setName()进行对名字的赋值 System.out.println(s.getName());//只能通过getNane()对名字进行调用 } }
回顾方法的重载:相同的名字,参数不同。
例如:println(); println()方法名相同,但是参数有很多种,有double,int,float,char,Object,String,各种类型。
判断两个方法是否相同 : 看方法名;参数列表;
2.继承
继承:ctrl + h 可以查看继承关系 --------- 以树结构的形式呈现
extands 继承本质是对某一批类的抽象,只有单继承。
继承是类和类之间的一种关系,此外还有依赖、组合、聚合关系。
继承关系的两个类,一个是子类,一个是父类,子类继承父类用extends来表示。
在java中所有的类都默认直接或间接的继承object类。
//继承的样式: public class Student extends Person{ }
父类中所有的属性和方法都可以被子类继承。只要子类继承了父类,其父类中所有的方法都会拥有。
子类中继承了父类中的属性和方法,在子类中能不能直接使用这些属性和方法,是看在父类中的修饰符(public,protected,default,private).
在以上四种权限范围内,私有的东西不能被继承,只有private不能直接对象.属性 或者 对象.方法。其余public,protected,default都可以在其他类中访问到。在Teacher类中进行测试:
***************Person类中:******************************* package oop.demo04; public class Person { private String name; int age = 10; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void say(){ System.out.println("会说话"); } } *****************Student类******************************* package oop.demo04; public class Student extends Person { private int id; private char sex; private double score; public int getId() { return id; } public void setId(int id) { this.id = id; } public char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } } *******************Teacher类******************************* package oop.demo04; public class Teacher extends Person{ private int age; char sex = '女'; protected int id = 456123; public String name = "张三"; @Override public int getAge() { return age; } @Override public void setAge(int age) { this.age = age; } } ********************Application类 测试类******************************* package oop.demo04; public class Application { public static void main(String[] args) { // 在Student类中的测试: // Student stu = new Student(); // stu.say(); // System.out.println(stu.age); // stu.setName("张三"); // System.out.println(stu.getName()); Teacher tea = new Teacher(); tea.setAge(45); System.out.println(tea.getAge()); System.out.println( tea.name); System.out.println( tea.id); System.out.println(tea.sex); } } ******************************测试结果:******************************* 45 张三 456123 女
3. Object类
java 中的每一个类都是"直接" 或者 "间接"的继承了Object类.
instanceof 属于
在Object类中,提供了一些方法被子类继承,那么就意味着,在java中,任何一个对象都可以调用这些被继承过来的方法。(因为Object是所以类的父类)
例如: toString 方法、equals方法、getClass 方法等
注:Object类中的每一个方法之后都会使用到.
4.super类
super类代表父类,this类代表当前类。
举例1:子类调用父类的属性测试
************************************父类 Person类******************************* public class Person { protected String name = "父亲person"; } ************************************子类 Student类******************************* public class Student extends Person { private String name = "儿子student"; public void test(String name){ System.out.println(name);//当前参数传递值 在测试类中传入的值 System.out.println(this.name);//当前儿子类中的属性:儿子 System.out.println(super.name);//父类中的属性:父亲 } } ***********************************测试类 Application类****************************** public class Application { public static void main(String[] args) { Student stu = new Student(); stu.test("测试名字" ); } } *********************************************测试结果:******************************* 测试名字 儿子student 父亲person
举例2: 子类调用父类的方法测试 但是如果父类的属性或者方法是私有的,子类中就无法调用。
***********************************父类 Person类 *********************************** public class Person { public void print(){ System.out.println("Person"); } } ***********************************子类 Student类 *********************************** public class Student extends Person { public void print(){ System.out.println("Student"); } public void test2(){ print();// Student 当前方法的值 this.print();// Student 本类中方法的值 super.print();// Person 父类方法的值 } ***********************************测试类 Application类******************************* public class Application { public static void main(String[] args) { Student stu = new Student(); stu.test2(); } *************************************测试结果 : ************************************* Student Student Person
举例3: 无参构造器的调用
1.调用一个对象先走无参构造器 2.先执行父类的构造器,再执行子类的构造器。原因是:在子类的构造器第一行里有隐形隐藏的父类无参构造器 ***********************************父类 Person类 ************************************ public class Person { public Person(){ System.out.println("父类无参构造器"); } } ***********************************子类 Student类 *********************************** public class Student extends Person { public Student(){ //隐藏代码:调用了父类的无参构造 super();//只能在第一行出现 默认的,不写也调用 System.out.println("子类无参构造器"); } } ***********************************测试类 Application类******************************* public class Application { public static void main(String[] args) { Student stu = new Student(); } } *************************************测试结果 : ************************************* 父类无参构造器 子类无参构造器
举例4: 子类无参调用父类有参构造器
***********************************父类 Person类 ************************************ public class Person { //没有显性写出无参构造器 public Person(String name){ System.out.println("父类有参构造器"); } } ***********************************子类 Student类 *********************************** public class Student extends Person { public Student(){ super("name");//调用父类有参构造器 System.out.println("子类无参构造器"); } } ***********************************测试类 Application类******************************* public class Application { public static void main(String[] args) { Student stu = new Student(); } } *************************************测试结果 : ************************************* 父类有参构造器 子类无参构造器
Super 注意点:
-
super调用父类的构造方法,必须在构造方法的第一行。super();
-
super 必须只能出现在子类的方法或者构造方法中!
-
super 和 this不能同时调用构造方法!
this:
-
代表的对象不同。this代表本身调用者的对象。super代表父类对象的应用。
-
this();必须在构造器的第一行。
-
使用前提不同:this没有继承也可以使用,super只能在继承后才可以使用。
-
构造方法不同:this();调用本类的构造,super();调用父类的构造!
构造器使用:
1.调用构造器只能调用一个,要么调用父类,要么调用子类。
2.一个类默认构造器是无参构造器,只要重写有参构造器,无参构造器就得显性表示。
3.如果父类中没有显示表达无参构造器,在子类中要调用父类的构造器,可以调,不过必须调用父类的有参构造器。
5.方法的重写 override
1.前提:需要有继承关系,子类重写父类的方法!
2.方法名必须相同
3.参数列表必须相同
4.修饰符:范围可以扩大但是不能缩小。public > protected > default > private
5.抛出异常:范围可以被缩小,但是不可以扩大。ClassNotFoundException(小) ---> Exception(大)
静态方法和非静态方法的区别很大!
1.在static修饰下重写: static静态方法:方法的调用只和左边定义的数据类型有关 static和类一起加载 ***********************************父类 B类 **************************************** public class B { public static void print(){ System.out.println("B"); } } ***********************************子类 A类 **************************************** public class A extends B { public static void print(){ System.out.println("A"); } } ***********************************测试类 Application类******************************* public class Application { //在static修饰下 方法的调用只和左边定义的数据类型有关 public static void main(String[] args) { A a = new A(); a.print(); //A //父类的引用指向了子类 B b = new A(); b.print();//B } } *************************************测试结果 : ************************************** A B
非静态的方法才有重写 ***********************************父类 B类 **************************************** public class B { public void print(){ System.out.println("B"); } } ***********************************子类 A类 **************************************** public class A extends B { public void print(){ System.out.println("A"); } } ***********************************测试类 Application类******************************* public class Application { public static void main(String[] args) { A a = new A(); a.print(); //接收对象B B b = new A(); b.print(); } } *************************************测试结果 : ************************************** A A
重写都是方法的重写,和属性无关,方法体不同!
子类继承父类进行重写它的方法。必须是public修饰的,private不可以而且是非静态的,如果是static不可以重写。
为什么需要重写? 父类的功能子类不一定需要,或者不一定满足。 alt + Insert ---> override
6.多态
动态编译:类型:可扩展性
多态性是指允许不同类的对象对同一消息作出响应。
对象,是具体的事物。类,是抽象的,是对对象的抽象。从代码运行角度考虑先有类后有对象。类是对象的模板。
一个对象的实际类型是确定的,但可以指向对象引用的类型有很多(父类或者有关系的类)
相同类域的不同对象,调用相同方法,表现出不同的结果。
一个对象的实际类型是确定的,new Student(), new Person(); new Student(); new Person();
指向对象的引用类型却是任意的可以是 Student,Person,Object. Student s1 = new Student(); Person s2 = new Student();//父类的引用指向子类对象 必须有关系 Object s3 = new Student(); //可以通过父类去new子类 // String s4 = new Student(); String 与 Student 没有关系 所以不可以
s2.方法(),在子类没有重写方法时走的还是父类的方法 s2.run();//虽然new Student(),但还是走的父类方法 因为子类继承了父类全部方法 s2.run();//如果子类重写父类的方法,那么执行子类的方法 s1.run();
多态的调用: 子类和父类都有的方法,子类没有重写父类的,就调用父类里的方法。如果子类重写了父类的方法,就调用子类的。 对象能执行那些方法,主要看对象左边的类型,和右边关系不大! 子类的引用和父类的引用不一样 子类能调用的方法是student里的,或者继承出来的方法。 父类型 可以指向子类,但是不能调用子类独有的方法 运行时和动态方法绑定 --- 因为之间存在类型转化
***********************************父类 Person类 ************************************** public class Person { public void run(){ System.out.println("Person run"); } } ***********************************子类 Student类 ************************************** public class Student extends Person { @Override public void run() { System.out.println("Student run"); } public void eat(){ System.out.println("eat"); } } ***********************************测试类 Application类 ******************************* Student s1 = new Student(); Person s2 = new Student();//父类的引用指向子类对象 必须有关系 Object s3 = new Student(); //可以通过父类去new子类 s2.run();//虽然new Student(),但还是走的父类方法 因为子类继承了父类全部方法 s2.run();//子类重写父类的方法,执行子类的方法 s1.run(); ((Student) s2).eat();//不能直接调用子类里特有的方法,Person里没有eat(); 高 --> 低 强制类型转换 *************************************测试结果 : ************************************** Student run Student run Student run eat
多态注意事项:
-
多态是方法的多态,属性没有多态
-
父类和子类要有联系 类型转换异常 ! ClassCastException!
-
存在条件 : 必须有继承关系 方法需要重写,父类的引用指向子类对象! Father f1 = new Son();
方法不能重写:
-
static 修饰的方法,属于类,不属于实例
-
final 常量
-
private 方法,私有的方法也不可以被重写