一、包
1.1包的基础概念
1.2包的本质
包的本质实际上就是创建不同的文件夹来保存类文件,示意图如下:
包就是两个文件夹,同一个包下方法的名称不能相同,但不同包下方法的名称可以相同。虽然名称相同,但这可以是两个完全不相同的类。
1.3包的基本代码
引入包
package com.use; import com.baostudy.Dog; public class test { public static void main(String[] args) { Dog dog = new Dog(); com.modifierStudy.Dog dog1 = new com.modifierStudy.Dog(); /* 为了区分两个dog,下面的用包名进行区分 本质用途还是一样的。 */ } }
一些常见的包
1.4包的相关细节
二、访问修饰符
2.1访问修饰符的基本概念
2.2访问修饰符的相关细节
三、封装
3.1封装的基础概念
封装就是把抽象出的数据[属性]和对数据的操作[方法]封装在一起,数据被保护在内部,程序其它部分只有通过被授权的操做[方法],才能对数据进行操作。(电视机就是一个例子,开关电视机在电视机内部是一个非常复杂的过程,但对于用户来说只需要按一下开关键。用户无法改变内部结构。)
3.2封装的实现
3.3封装的实例代码
要求如下:
package com.ssj.encap; public class Encapsulation01 { public static void main(String[] args) { Person person = new Person(); person.setName("jack"); person.setSalary(30000); person.setAge(30); System.out.println(person.name); //工资和年龄只有通过get才能查到,不能直接查到 //可以在get上增加一些逻辑比如:密码。才能查询 person.getSalary("admin"); person.getAge("aaaaa"); } } class Person{ public String name; private int age; private double salary; //自己写setxxx和getxxx太慢了,使用快捷键。 //alt+insert选择(Getter and Setter) //然后根据要求完善代码 public String getName() { return name; } public void setName(String name) { this.name = name; } public void getAge(String lock) { if(lock == "admin") { System.out.println(age); } else{ System.out.println("密码错误,没有权限访问年龄"); } } public void setAge(int age) { if (age >= 1 && age <= 120) { this.age= age; } else{ System.out.println("你设置的年龄不对,年龄需要在 1-120 ,给你默认年龄18"); this.age = 18; } } public void getSalary(String lock) { if(lock == "admin") { System.out.println(salary); }else{ System.out.println("密码错误,没有权限访问工资"); } } public void setSalary(double salary) { this.salary = salary; } }
由上可知封装的好处:1.可以隐藏实现细节2.可以对数据进行验证(set方法),保证安全合理(在get中增加逻辑)。
上述代码有个问题,因为在实际应用的过程中会顺手写构造器,以便随时能用。(就不用一个参数一个set方法了)如果使用构造器进行赋值的话就可以绕过set方法,这样就不能验证了。解决代码如下:
public Person(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; setSalary(salary); setName(name); setAge(age); }
在构造器中调用set方法就可以避免这个问题了。
package com.ssj.encap; public class Encapsulation01 { public static void main(String[] args) { Person person = new Person("jack",30,30000); System.out.println(person.name); person.getSalary("admin"); person.getAge("aaaaa"); //工资和年龄只有通过get才能查到,不能直接查到 //可以在get上增加一些逻辑比如:密码。才能查询 } } class Person{ public String name; private int age; private double salary; //自己写setxxx和getxxx太慢了alt+insert //选择(Getter and Setter) //然后根据要求完善代码 public Person(String name, int age, double salary) { this.name = name; this.age = age; this.salary = salary; setSalary(salary); setName(name); setAge(age); } public String getName() { return name; } public void setName(String name) { this.name = name; } public void getAge(String lock) { if(lock == "admin") { System.out.println(age); } else{ System.out.println("密码错误,没有权限访问年龄"); } } public void setAge(int age) { if (age >= 1 && age <= 120) { this.age= age; } else{ System.out.println("你设置的年龄不对,年龄需要在 1-120 ,给你默认年龄18"); this.age = 18; } } public void getSalary(String lock) { if(lock == "admin") { System.out.println(salary); }else{ System.out.println("密码错误,没有权限访问工资"); } } public void setSalary(double salary) { this.salary = salary; } }
四、继承
4.1继承的基础概念
先看两段代码;
package com.extend; //大学生考试 public class Graduate { public String name; public int age; private double score; public void setScore(double score) { this.score = score; } public void testing(){ System.out.println(" 大学生 " + name + " 正在考大学数学 "); } public void showInfo(){ System.out.println(" 学生名 " + name + " 年龄 " + age + " 成绩 " + score); } }
package com.extend; //小学生考试 public class pupil { public String name; public int age; private double score; public void setScore(double score) { this.score = score; } public void testing(){ System.out.println(" 小学生 " + name + " 正在考小学数学 "); } public void showInfo(){ System.out.println(" 学生名 " + name + " 年龄 " + age + " 成绩 " + score); } }
通过看上述两段代码不难发现,代码中有很多重复的部分也有不重复的部分,对于重复部分其实是学生的共有属性,重复写很麻烦,可以采取继承的方式解决这一问题。
4.2继承的基本代码
对于开头的代码运用继承进行优化。
父类:
package com.extend.improve_; //父类:是pupil和graduate的父类 public class student { //共有属性 public String name; public int age; private double score; //共有方法 public void setScore(double score) { this.score = score; } public void showInfo(){ System.out.println(" 学生名 " + name + " 年龄 " + age + " 成绩 " + score); } }
子类:
package com.extend.improve_; public class pupile extends student{ public void testing(){ System.out.println(" 小学生 " + name + " 正在考小学数学 "); } }
package com.extend.improve_; public class Graduate extends student{ public void testing(){ System.out.println(" 大学生 " + name + " 正在考大学数学 "); } }
主函数
package com.extend.improve_; public class Extends01 { public static void main(String[] args) { pupile pupile = new pupile(); pupile.name = "银角大王"; pupile.age = 10; pupile.testing(); pupile.setScore(60); pupile.showInfo(); System.out.println("========"); Graduate graduate = new Graduate(); graduate.name = "金角大王"; graduate.age = 22; graduate.testing(); graduate.setScore(100); graduate.showInfo(); } }
4.3继承的本质
4.4继承的相关细节
(1)子类继承了所有的属性和方法,但是私有(private)属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问。
private int name = 10; public void getName{ System.out.println(name) } private void test400(){ System.out.println("test400"); } public void getTest400(){ test400(); }
(2)子类必须调用父类的构造器,完成父类的初始化。
(3)当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。[对于上面这段话可以一句一句去理解]
当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器
package com.extend.improve_; public class Sub extends Base { public Sub(){ //super()默认调用父类的无参构造器 System.out.println("子类sub()构造器被调用"); } //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器 public Sub(String name){ System.out.println("子类Sub()构造器被调用"); } public void sayOk(){ //非私有的属性和方法可以在子类直接访问 //但是私有属性和方法不能在子类直接访问 System.out.println(n1+" "+n2+" "+n3); test100(); test200(); test300(); } }
package com.extend.improve_; public class Base { public int n1 = 100; protected int n2 = 200; int n3 = 300; private int n4 = 400; public Base(){ System.out.println("父类Base()构造器被调用"); } public int gtN4(){ return n4; } public void test100(){ System.out.println("test100"); } protected void test200(){ System.out.println("test200"); } void test300(){ System.out.println("test300"); } private void test400(){ System.out.println("test400"); } public void getTest400(){ test400(); } }
package com.extend.improve_; public class extemdsDetail { public static void main(String[] args) { Sub sub = new Sub();//创建一个子类对象 System.out.println("===第二个对象==="); Sub sub1 = new Sub("jack"); } }
通过上述代码及其运行结果可以看出,只调用了子类的构造器,父类的构造器也被调用了。
如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。
因为子类中的super()默认(super是隐含存在的,只是编译器自带的)调用父类的无参构造器,而父类没有加无参构造器,因此代码报错。解决办法:
package com.extend.improve_; public class Sub extends Base { public Sub(){ super("smith",10); System.out.println("子类sub()构造器被调用"); } //当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器 public Sub(String name){ super("tom",30);//因为父类中没有无参构造器 //需要super去指定调用父类的哪一个构造器 System.out.println("子类Sub()构造器被调用"); } public void sayOk(){ //非私有的属性和方法可以在子类直接访问 //但是私有属性和方法不能在子类直接访问 System.out.println(n1+" "+n2+" "+n3); test100(); test200(); test300(); } }
(4)如果希望指定去调用父类的某个构造器,则显式的调用一下:super()
(5)super在使用时,需要放在构造器的第一行(因为是先调用父类的构造在再调用子类的构造器)
(6)super和this都只能放在构造器的第一行。因次这两个方法不能同时存在在同一个构造器内
(7)java所有类都是object类的子类(通过快捷键ctrl+H(IEDA))
(8)父类构造器的调用不限于直接父类,将一直往上追溯直到Object(顶级父类)
(9)子类最多只能继承一个父类,即java中是单继承机制,即(A->B,A->C(->代表继承))是不可实现的。
(10)不能滥用继承,子类和父类必须满足is -a的逻辑关系
五、super关键字
5.1super关键字的基础概念
super代表父类的引用,用于访问父类的属性、方法、构造器。
(1)访问父亲的属性,但不能访问父亲的private属性
(2)访问父亲的方法,但不能访问父亲的private方法
(3)访问父亲的构造器
5.2super关键字的基础代码
父类:
package com.super_; public class A { public int n1 = 100; protected int n2 = 200; int n3 = 300; private int n4 = 400; public A(){} public A(String name){} public A(String name,int age){} public void test100(){ } public void test200(){ } void test300(){ } private void test400(){ } }
子类:
package com.super_; public class B extends A{ //访问父类的属性,但不能访问父类的private属性 public void hi(){ System.out.println(super.n1+" "+super.n2+" "+super.n3); } //访问父类的方法,但不能访问父类的private方法 public void ok(){ super.test100(); super.test200(); super.test300(); //super.test400();不能访问父类私有的方法 } //访问父类的构造器:super(参数列表);只能放在构造器的第一句,只能出现一句! public B(){ super(); //super("jack"); //super("jack",10); } }
5.3super关键字的相关细节
1.调用父类构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)
2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父亲的成员,必须通过super。如果没有重名,使用super、this、直接访问时一样的效果。
3.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类(上级类)中有同名成员,使用super访问遵循就近原则。
今天的文章 面相对象中级(包、访问修饰符、封装、继承、super关键字)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/87786.html