Java大数据开发和安全开发
- (一)Java的封装
- 1.1 什么是封装
- 1.1.1 封装的设计规范
- 1.1.2 代码层面如何控对象的成员公开或隐藏?
- 1.2 JavaBean(实体类)
- 1.2.1创建实体类
- 1.2.2 实体类有啥应用场景?
- 1.2.3 实体类总结
- 1.3 继承
- 1.3.1 继承的语法格式
- 1.3.2 继承的执行原理
- 1.3.3 使用继承有啥好处?
- 1.3.4 继承的注意事项
- 1.3.4.1 权限修饰符
- 1.3.4.2 单继承、0bject类
- 1.3.4.3 方法重写
- 1.3.4.4 子类中访问其他成员的特点
- 1.3.4.5 子类构造器的特点
- 1.4 多态
- 1.4.1 什么是多态?
- 1.4.2 多态的具体代码体现
- 1.4.3 使用多态的好处
- 1.4.4 类型转换
(一)Java的封装
1.1 什么是封装
- 就是用类设计对象处理某一个事物的数据时,应该把要处理的数据,以及处理这些数据的方法,设计到一个对象中去
- 要处理的数据
- 处理数据的方法
- 写到一个类里就是封装 如下
1.1.1 封装的设计规范
- 合理隐藏
- 合理暴露
- private
public class Student {private String name; double chinese; double math;private void printTotalScore() { System.out.println(name + "的总成绩是:" + (chinese + math));}public void printAverageScore() {System.out.println(name + "的平均成绩是:" + (chinese + math) / 2.0);}
}
怎么达到合理隐藏 合理暴露呢
控制输入
控制输出
为了防止别人随意传值,使用私有化变量,然后让用户通过公有方法访问给私有变量赋值
public class Student {private String name; // 私有变量 不允许访问private double score;private double math;public void setScore(String name,double score,double math){if ((score >= 0 && score <= 100) && (math >=0 && math<=100)){this.name = name;this.score = score;this.math = math;} else {System.out.println("数据非法");}}public double getScore(){return score;}private void printTotalScore() { // 私有方法 不允许访问System.out.println(name + "的总成绩是:" + (chinese + math));}public void printAverageScore() {System.out.println(name + "的平均成绩是:" + (chinese + math) / 2.0);}
}
public class Test {public static void main(String[] args) {// 目标:掌握封装的设计规范:合理隐藏、合理暴露。Student s1 = new Student();s1.setScore("liyang",55,66);System.out.println(s1.getScore());}
}
1.1.2 代码层面如何控对象的成员公开或隐藏?
- 公开成员,可以使用public(公开)进行修饰。
- 隐藏成员,使用private(私有,隐藏)进行修饰。
1.2 JavaBean(实体类)
什么是实体类?
- 就是一种特殊形式的类。
1.2.1创建实体类
- 1.先创建两个私有变量
public class Student {private String name;private double score;
}
2.选中变量右键选择generate,可以创建有参构造器,set方法,get方法
- 3.无参构造方法选择selec none
public class Student {//1、必须私有成员变量,并为每个成员变量都提供getset方法private String name;private double score;//2、必须为类提供一个公开的无参数构造器public Student() {}public Student(String name, double score) {this.name = name;this.score = score;}public void setName(String name) {this.name = name;}public void setScore(double score) {this.score = score;}public String getName() {return name;}public double getScore() {return score;}
}
public class Test {public static void main(String[] args) {//目标:掌握实体类的书写要求、特点、应用场景Student s1 = new Student();s1.setName("播妞");s1.setScore(99);System.out.println(s1.getName());System.out.println(s1.getScore());}
}
1.2.2 实体类有啥应用场景?
- 实体类只负责数据存取,而对数据的处理交给其他类来完成,以实现数据和数据业务处理相分离
操作类处理数据
public class StudentOperator {private Student student;public StudentOperator(Student student) {this.student = student;}public void printPass() {if (student.getScore() >= 60) {System.out.println(student.getName() + "学生成绩及格");} else {System.out.println(student.getName() + "学生成绩不及格");}}
}
实体类保存数据
```java
public class Test {public static void main(String[] args) {//目标:掌握实体类的书写要求、特点、应用场景Student s1 = new Student();s1.setName("播妞");s1.setScore(99);System.out.println(s1.getName());System.out.println(s1.getScore());StudentOperator operator =new StudentOperator(s1);operator.printPass();}
}
1.2.3 实体类总结
- 什么是实体类?有啥特点?
- 成员变量必须私有,且要为他们提供get、set方法;必须有无参数构造器
- 仅仅只是一个用来保存数据的java类,可以用它创建对象,保存某个事物的数据。
- 实体类有啥应用场景?
- 实体类对应的是软件开发里现在比较流行的开发方式,数据和数据的业务处理相分离
1.3 继承
1.3.1 继承的语法格式
- Java中提供了一个关键字extends,用这个关键字,可以让一个类和另一个类建立起父子关系。
继承的特点
- 子类能继承父类的非私有成员(成员变量、成员方法)
继承后对象的创建
- 子类的对象是由子类、父类共同完成的。
先写一个类A
public class A{//公开成员public int i;public void print1(){System.out.println("===print1===");}// 私有成员private int j;private void print2(){System.out.println("===print2===");}
}
再写一个类B继承A
// 子类
public class B extends A{private int k; //子类是可以继承父类的非私有成员public void print3(){System.out.println(i); //直接访问A的公开成员和方法print1();// System.out.println(j);// print2();
那如果此时我们创建一个对象b 这个b可以继承那些东西?
此时的b是由A和B两个设计图共同创建的表,可以使用A和B的所有公开成员变量和方法
public class Test {public static void main(string[] args){// 目标:认识继承、掌握继承的特点。B b = new B();System.out.println(b.i);// System.out.println(b.j);// System.out.println(b.k);b.print1();//b.print2();b.print3();
1.3.2 继承的执行原理
当创建一个B对象时,具体的过程如下:
- 类加载:JVM 会将A类和B类的字节码加载到方法区中。方法区存储了类的元数据,包括类的定义、常量、静态变量和方法。
- 实例化B对象:在堆内存中创建一个B对象的实例。堆内存用于存储对象的实例数据。
- 继承属性:B对象会继承A类的公开成员变量i。这意味着B对象具有A类的公开属性,可以直接访问和使用。
- 方法继承:B类继承了A类的公开方法print1。因此,B对象可以调用print1方法,就像它是自己的方法一样。
- 私有成员限制:由于j是A类的私有成员,根据 Java 的封装原则,子类(B)无法直接访问父类的私有成员。尝试访问b.j会导致编译错误。
- 子类特有属性:B类定义了自己的私有成员变量k,它是B类特有的,与父类A无关。
- 在方法区中,存储了类的信息,包括类的定义、方法和变量。方法区中的数据在程序运行期间是共享的。
- 栈内存用于方法调用和局部变量的存储。当调用B类的方法时,相关的方法参数和局部变量会被压入栈中。
- 堆内存用于存储对象实例。每个对象都有自己的内存空间,包括继承自父类的成员和子类自己定义的成员。
1、什么是继承?继承后有啥特点 ?
- 继承就是用extends关键字,让一个类和另一个类建立起一种父子关系。.
- 子类可以继承父类非私有的成员。
2、带继承关系的类,Java会怎么创建它的对象?对象创建出来后,可以直接访问哪些成员?
- 带继承关系的类,java会用类和其父类,这多张设计图来一起创建类的对象。
- 对象能直接访问什么成员,是由子父类这多张设计图共同决定的,这多张设计图对外暴露了什么成员,对象就可以访问什么成员。
1.3.3 使用继承有啥好处?
- 减少重复代码的编写。
继承的案列讲解
这两个类存在大量重复代码 怎么能简化一下,省去编写这么的重复代码的力气呢
那就是采用继承,让两个类继承重复的代码,然后直接调用
先新建一个People类
public class People {private String name;public string getName(){return name;}public void setName(string name){this.name = name;}
在创建一个教师类继承People类
public class Teacher extends People{private string skill;public string getSkill(){return skill;}public void setSkill(string skill){this.skill = skill;}
在创建一个咨询师类继承People类
public class ConsuIktant extends People{private int number;public int getNumber(){return number;}public void setNumber(int number){this.number = number;}
在写一个Test类 使用main方法是作为Java 程序的入口点 调用其他方法等,从而控制程序的执行顺序和逻辑。
public class Test {public static void main(string[]args){// 目标:搞洁楚继承的好处。Teacher t= new Teacher();t.setName(“播仔");t.setSkill("Java、Spring");System.out.println(t.getName());System.out.println(t.getskill());t.printInfo();}
}
1.3.4 继承的注意事项
1.3.4.1 权限修饰符
- 什么是权限修饰符?
- 就是是用来限制类中的成员(成员变量、成员方法、构造器、代码块…)能够被访问的范围。
- 权限修饰符有几种?各自的作用是什么?
编写一个修饰符的测试类
public class Fu {// 1、私有:只能在本类中访问private void privateMethod(){System.out.println("==private==");}// 2、缺省:本类,同一个包下的类void method(){System.out.println("==缺省==");}// 3、protected:本类,同一个包下的类,任意包下的子protected void protectedMethod(){System.out.println("==protected==");}// 4、public: 本类,同一个包下的类,任意包下的子类,public void publicMethod(){System.out.println("==public==");}// 5、本类中测试调用不同修饰符的方法public void test(){privateMethod();method();protectedMethod();publicMethod();}
在同一个包类下的其他类调用不同修饰符的方法
public class Demo {public static void main(string[]args){// 目标:掌握不同权限修饰符的作用。Fu f = new Fu();// f.privateMethod(); 不允许调用私有方法f.method();f.protectedMethod();f.publicMethod();}
}
在任意包下的子类
里调用不同修饰符的方法
public class Zi extends Fu {public void test(){// privateMethod();// 报错// method();// 报错protectedMethod();publicMethod();}
}
在任意包下的任意类里调用不同修饰符的方法
public class Demo2{public static void main(string[] args){Fu f = new Fu();// f.privateMethod();// 报错// f.method();// 报错// f.protecedMethod();// 报错f.publicMethod(); //完全暴露}
}
1.3.4.2 单继承、0bject类
- Java是单继承的,Java中的类不支持多继承,但是支持多层继承
public class Test {public static void main(String[]args){//目标:掌握继承的两个注意事项事项。// 1、Java是单继承的:一个类只能继承一个直接父类;Java中的类不支持多继承,但是支持多层继承。//2、0bject类是Java中所有类的祖宗。}
class A{}
class B extends A{}
class C extends B,A{} // 报错
class D extends B{} //D 继承B B继承A 这就是多层继承
}
为何Java中的类不支持多继承
请看如下反证法:
0bject类
object类是java所有类的祖宗类。我们写的任何一个类,其实都是object的子类或子孙类。
class A{}
//实际默认继承了0bject类
class A{}//extends 0bject{}
public class Test {public static void main(String[]args){//目标:掌握继承的两个注意事项事项。// 1、Java是单继承的:一个类只能继承一个直接父类;Java中的类不支持多继承,但是支持多层继承。//2、0bject类是Java中所有类的祖宗。A a= new A();a.如下图会自动显示多个方法 这些方法都是0bject类的}
- B类就是0bject类的孙子类 B继承了A 继承了0bject类 B也就继承了0bject类
class A{}
class B extends A{}
B b = new B();
b.如下图会自动显示多个方法 这些方法都是0bject类的
- object类是java所有类的祖宗类。我们写的任何一个类,其实都是object的子类或子孙类。
1.3.4.3 方法重写
- 当子类觉得父类中的某个方法不好用,或者无法满足自己的需求时,子类可以重写一个方法名称,参数列表一样的方法,去覆盖父类的这个方法,这就是方法重写。
- 注意:重写后,方法的访问,Java会遵循就近原则
方法重写的其它注意事项
- 重写小技巧:使用Override注解,他可以指定java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好,
- 子类重写父类方法时 访问权限必须大于或者等于父类该方法的权限(public>protected>缺省)
- 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。
- 私有方法、静态方法不能被重写,如果重写会报错的。
私有方法、静态方法不能被重写,如果重写会报错的。
方法重写在开发中的常见应用场景
子类重写0bject类的toString()方法,以便返回对象的内容
public class student extends 0bject{private String name;private int age;public student(){}public Student(String name,int age){this.name = name;this.age = age;}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;}
输出对象时默认调用的就是tostring 但是object类自带的toString方法返回的东西是内存地址,不是我们想要的
public class Test {public static void main(string[]args){// 目标:认识方法重写,掌握方法重写的常见应用场景。Bb=new B();b.print1();b.print2( a:2,b:3);System.out.println("-------------------------")Students =new Student( name:"播妞",age: 19);//System.out.println(s.tostring()); System.out.println(s); //输出对象时默认调用的就是tostring
@Overridepublic string tostring(){return "Student{name=" + name + ",age=" + age + "}";}
完整代码
public class student extends 0bject{private String name;private int age;public student(){}public Student(String name,int age){this.name = name;this.age = age;}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;}@Overridepublic string tostring(){return "Student{name=" + name + ",age=" + age + "}";}
Student{name=播妞,age=19}
右键还可以自动生成重写代码 选择tostring
1.3.4.4 子类中访问其他成员的特点
1、在子类方法中访问其他成员(成员变量、成员方法),是依照就近原则的
- 先子类局部范围找。
- 然后子类成员范围找。
- 然后父类成员范围找,如果父类范围还没有找到则报错
2、如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的怎么办?可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法
- 访问重名的成员变量name 会就近选择方法内部的name
- 访问子类的变量就需要使用this.子类变量 访问父类 super.父类变量
就近原则
- 访问重名的成员方法
- 访问父类方法使用super.父类方法() 访问子类方法使用子类方法()
就近原则
1.3.4.5 子类构造器的特点
- 子类的全部构造器,都会先调用父类的构造器,再执行自己
class F{public F(){System.out.println("===父类F的 无参数构造器 执行了===");}
class Z extends F{public 2(){// super();// 默认存在的System.out.println("===子类Z的 无参数构造器 执行了===");}public Z(String name){//super();// 默认存在的System.out.println("===子类Z的 有参数构造器 执行了===");}
public class Test{public static void main(String[]args){// 目标:先认识子类构造器的特点,再掌握这个特点的常见应用场景。Z z= new Z();Z z2= new Z( name:"播妞");}
}
父类只有有参构造器了 ,子类的super会报错,要不想报错就让super调用有参构造器 super( name:“播妞”,age: 17);
class F{//public F(){//System.out.println("===父类F的 无参数构造器 执行了===");//}public F(String name,int age){System.out.println("===父类F的 无参数构造器 执行了===");}class Z extends F{public 2(){// super();// 默认存在的super( name:"播妞",age: 17);System.out.println("===子类Z的 无参数构造器 执行了===");}public Z(String name){//super();// 默认存在的super( name:"播妞",age: 17);System.out.println("===子类Z的 有参数构造器 执行了===");}
public class Test{public static void main(String[]args){// 目标:先认识子类构造器的特点,再掌握这个特点的常见应用场景。Z z= new Z();Z z2= new Z( name:"播妞");}
}
子类构造器是如何实现调用父类构造器的
- 默认情况下,子类全部构造器的第一行代码都是super()(写不写都有),它会调用父类的无参数构造器
- 如果父类没有无参数构造器,则我们必须在子类构造器的第一行手写super(…),指定去调用父类的有参数构造器
目标:搞清楚子类构造器为什么要调用父类构造器,有啥应用场景上
public class Test2{public static void main(String[]args){//1 目标:于类调用父类构造器的常见应用场景。Teacher t= new Teacher("李四",36,"Java");System.out.println(t.getName());System.out.println(t.getAge());System.out.println(t.getski11());
class People{private string name;private int age;public People(){}public People(string name, int age){this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}
class Teacher extends People{private string skill;public Teacher(){}public Teacher(string name,int age, string skill){super(name,age);this.skill =skill;}public String getSkill() {return skill;}public void setSkill(String skill) {this.skill = skill;}
}
子类构造器调用父类构造器的执行原理
- 子类构造器可以通过调用父类构造器,把对象中包含父类这部分的数据先初始化赋值
- 再回来把对象里包含子类这部分的数据也进行初始化赋值。
public Teacher(string name,int age, string skill){super(name,age);this.skill =skill;}
this(…)调用兄弟构造器
- 任意类的构造器中,是可以通过this(…)去调用该类的其他构造器的
public class Test {public static void main(String[] args) {//! 需求:如果学生没有填写学校,那么学校默认就是黑马程序员Student s2 = new Student( name:"张三",age: 28);System.out.println(s2.getName());System.out.println(s2.getAge());System.out.println(s2.getSchoolName());}class Student{private String name;private int age;private String schoolName;public Student() {}public Student(string name, int age){//this.name = name;//this.age = age;//this.schoolName = "黑马程序员";this(name,age,schoolName:"黑马程序员"); //任意类的构造器中,是可以通过this(...)去调用该类的其他构造器的}public Student(String name, int age, String schoolName) {this.name = name;this.age = age; //this调用的就是这个类this.schoolName = schoolName;}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 String getSchoolName() {return schoolName;}public void setSchoolName(String schoolName) {this.schoolName = schoolName;}
}
this(…)和super(…)使用时的注意事项:
- this(…)、super(…)都只能放在构造器的第一行,因此,有了this(…)就不能写super(…)了,反之亦然。
1.4 多态
1.4.1 什么是多态?
- 多态是在继承/实现情况下的一种现象,表现为:
对象多态
、行为多态
。
1.4.2 多态的具体代码体现
public class People {public void run(){System.out.println("人跑得很快");}
}
public class Teacher extends People{@Overridepublic void run() {System.out.println("老师跑得很快");}
}
public class Student extends People{@Overridepublic void run() {System.out.println("学生跑的很快");}
}
识别技巧:编译看左边,运行看右边 就是编译的时候编译people 运行的时候按照student类运行 在student类里寻找
public class Test {public static void main(String[] args) {// 目标:认识多态:对象多态,行为多态。// 1、对象多态People P1 = new Teacher();P1.run();//识别技巧:编译看左边,运行看右边People P2 = new Student();P2.run();}
}
多态的前提
- 有
继承/实现
关系存在父类引用子类对象
存在方法重写
多态的一个注意事项
- 多态是对象、行为的多态,Java中的属性(成员变量)不谈多态。
- 对于变量,编译看左边,运行看左边 就是看people中有什么就是执行什么
public class Test {public static void main(String[] args) {// 目标:认识多态:对象多态,行为多态。// 1、对象多态People P1 = new Teacher();P1.run(); // 识别技巧:编译看左边,运行看右边System.out.println(P1.name); //注意:对于变量,编译看左边,运行看左边People P2 = new Student();P2.run();}
}
1.4.3 使用多态的好处
- 在多态形式下,右边对象是解耦合的,更便于扩展和维护
- =号右边随时可以把Teacher换成Student 这就是解耦合
- 如果右边写死不能随时更换,那就是紧耦合
- 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利
public class Test {public static void main(string[] args){// 目标:理解多态的好处// 好处1:可以实现解耦合,右边对象可以随时切换,后续业务随机改变People p1=new student();p1.run();// 好处2:可以使用父类类型的变量作为形参,可以接收一切子类对象。Student s =new Student();go(s);Teacher t = new Teacher();go(t);public static void go(People p){}
多态下会产生的一个问题,怎么解决?
- 多态下不能使用子类的独有功能。
public class Teacher extends People{@Overridepublic void run() {System.out.println("老师跑得很快");}public void test(){System.out.println("老师需要教知识~~~");}
}
public class Student extends People{@Overridepublic void run() {System.out.println("学生跑的很快");}public void test(){System.out.println("学生需要考试~~~");}
}
public class Test {public static void main(string[] args){// 目标:理解多态的好处// 好处1:可以实现解耦合,右边对象可以随时切换,后续业务随机改变People p1=new student();p1.run();p1.test();//报错 多态下存在的问题:无法直接调用子类的独有功能。 因为编译看左边people people里面没有test// 好处2:可以使用父类类型的变量作为形参,可以接收一切子类对象。Student s =new Student();go(s);Teacher t = new Teacher();go(t);public static void go(People p){}
1.4.4 类型转换
- 自动类型转换:父类 变量名=new 子类();
- 强制类型转换:子类 变量名=(子类)父类变量
强制类型转换的一个注意事项
存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错
运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常(ClassCastException)的错误出来。
public class Test {public static void main(string[] args){// 目标:理解多态的好处// 好处1:可以实现解耦合,右边对象可以随时切换,后续业务随机改变People p1=new student();p1.run();p1.test();//报错 多态下存在的问题:无法直接调用子类的独有功能。 因为编译看左边people people里面没有test// 强制类型转换Student s1=(student)p1;s1.test();//! 强制类型转换可能存在的问题:编译阶段有继续或者实现关系就可以强制转换,但是运行时可能出现类型转换异常Teacher t1 = (Teacher) p1; // 运行时出现了:ClassCastException// 好处2:可以使用父类类型的变量作为形参,可以接收一切子类对象。Student s =new Student();go(s);Teacher t = new Teacher();go(t);public static void go(People p){}
强转前,Java建议:
- 使用instanceof关键字,判断当前对象的真实类型,再进行强转。
p instanceof Student
public class Test {public static void main(string[] args){// 目标:理解多态的好处// 好处1:可以实现解耦合,右边对象可以随时切换,后续业务随机改变People p1=new student();p1.run();p1.test();//报错 多态下存在的问题:无法直接调用子类的独有功能。 因为编译看左边people people里面没有test// 强制类型转换Student s1=(student)p1;s1.test();//! 强制类型转换可能存在的问题:编译阶段有继续或者实现关系就可以强制转换,但是运行时可能出现类型转换异常Teacher t1 = (Teacher) p1; // 运行时出现了:ClassCastExceptionif(p1 instanceof Student){Student s2 = (student) p1;s2.test();}else {Teacher t2 = (Teacher) p1;t2.teach();}System.out.println("---------------------")// 好处2:可以使用父类类型的变量作为形参,可以接收一切子类对象。Student s = new Student();go(s);Teachert = new Teacher();go(t);public static void go(People p){p.run();if(p instanceof student){Students=(Student)p;s.test();}else if(p instanceof Teacher){Teachert=(Teacher)p;t.teach();}}}
}