一、四种访问修饰符的访问范围
二、封装
1.封装:
就是把属性和方法封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作方法,才能对数据进行操作。
封装的好处
(1)隐藏实现的细节。
(2)对数据进行验证,保证安全合理。
2.封装的实现步骤
(1)将属性进行私有化(不能直接修改属性)
(2)提供一个公共的(public)set方法,用于对属性判断并赋值。
(3)提供一个get方法,用于获取属性的值
案例如下:
设计一个小程序,不能随便查看人的年龄、工资等隐私,并对设置的年龄进行合理的验证。
年龄必须在1到120岁。工资不能直接查看。name的长度在2-6个字符。
代码如下:
package HanShunPing;
public class Encapsulation01 {
public static void main(String[] args) {
Person person = new Person();
person.setName("jack");
person.setAge(30);
person.setSalary(5000);
System.out.println(person.info());
System.out.println(person.getSalary());
Person smith = new Person("smith",2000,50000);
System.out.println("====smith====信息");
System.out.println(smith.info());
}
}
class Person{
public String name;
private int age;
private int salary;
//无参构造器 快捷键 alt+insert
public Person() {
}
//有参构造器
public Person(String name, int age, int salary) {
//这里这么设置的话会出现不合理的数据,使得数据限制失效
// this.name = name;
// this.age = age;
// this.salary = salary;
setSalary(salary);
setAge(age);
setName(name);
}
//快速get/set方法 笔记本alt+insert+fn 台式电脑不要fn
public String getName() {
return name;
}
public void setName(String name) {
//加入对数据的检测,相当于增加了业务逻辑
if (name.length() >= 2 && name.length() <= 6) {
this.name = name;
}else{
System.out.println("您的用户名不符合规则");
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 1 && age <= 120) {//如果是合理范围
this.age = age;
}else {//如果里年龄不合适
System.out.println("年龄需要在1到120岁,不在这个范围默认年龄为18");
this.age = 18;//设置一个默认年龄
}
}
public int getSalary() {//用来查看工资的多少,直接调用person.Salary是不行
//可以增加对当前对象的权限判断,权限不对就不返回
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String info() {
return "信息为" +
"名字=" + name +
",年龄=" + age +
", 薪水=" + salary ;
}
}
三、继承:
继承可以解决代码的复用,让编程更加接近人类的思维。当多个类存在相同的属性和方法时,可以从这些类中抽出相同部分并当做一个父类,所有子类不需要重新定义这些属性和方法,只需要extends来说明继承父类即可。
class 子类 extends 父类{
}
继承使用细节:
1. 子类继承了父类的所有属性和方法,非私有的属性和方法可以在子类访问,但是私有属性不能在子类直接访问,要通过公共的方法区访问。
测试代码:
//父类:
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 getN4(){
return n4;//提供一个公共方法让子类调用父类的私有方法
}
public void test1000() {
System.out.println("test()1000");
}
protected void test2000(){
System.out.println("test2000()");
}
void test3000(){
System.out.println("test3000()");
}
private void test4000(){
System.out.println("test4000()");
}
public void callTest4000(){
test4000();//提供一个公共方法,让子类通过这个方法调用父类的私有方法。
}
}
//子类:
public class Sub extends Base{
public Sub() {
System.out.println("Sub()");
}
public void sayOk(){
System.out.println(n1+n2+n3);
getN4();
}
}
//测试类:
public class ExtendsTest {
public static void main(String[] args) {
Sub sub = new Sub();
sub.sayOk();
sub.getN4();
sub.callTest4000();
sub.test2000();
sub.test3000();
}
}
2.
(1)子类必须调用父类构造器,完成父类的初始化.
(2)当创建子类对象时,不管使用哪个子类的哪个构造器,默认情况下总会先去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中使用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。(意思就是在给子类创建对象时第一件事是程序会自动先调用父类的无参构造器)
(3)如果父类有一个无参构造器,那么子类中什么也不用写,如果父类的无参构造器被覆盖了,那么必须在子类的每一个构造器中指定调用了父类的哪一个构造器
测试代码如下:
//父类
public class Base {
public int n1 = 100;
protected int n2 = 200;
int n3 = 300;
private int n4 = 400;
// public Base() {//父类无参构造器 当把父类的默认构造器注释时并且重新写了一个带参数的构造器
//,子类会进行报错,会找不到默认构造器,这时候要用super()在第一行指定用了哪个构造器
// System.out.println("父类base()构造器被调用...");
// }//构造器写在第一行
public Base(String name,int age){
System.out.println("父类(String name,int age)构造器被调用...");
}
public int getN4(){
return n4;//提供一个公共方法让子类调用父类的私有方法
}
public void test1000() {
System.out.println("test()1000");
}
protected void test2000(){
System.out.println("test2000()");
}
void test3000(){
System.out.println("test3000()");
}
private void test4000(){
System.out.println("test4000()");
}
public void callTest4000(){
test4000();//提供一个公共方法,让子类通过这个方法调用父类的私有方法。
}
}
//子类:
public class Sub extends Base {
public Sub() {//子类无参构造器
// super();//该句是默认存在的(写不写都有),默认调用父类的无参构造器
// super中什么也不写就是调用父类无参构造器,super()可以在括号中写相应的参数从
// 而调用相应的构造器
super("smith",10);
System.out.println("子类Sub()构造器被调用");
}
public Sub(String name) {
super("tom",10);
System.out.println("子类的(String name)构造器被调用");
}
public void sayOk(){
System.out.println(n1+n2+n3);
getN4();
}
//测试类
public class ExtendsTest {
public static void main(String[] args) {
Sub sub = new Sub();
Sub sub2 = new Sub("jack");
//在创建子类对象时,会自动先调用父类的无参造器,如果父类没有无参构造器,
// 那么必须指定其他的构造器来对父类的初始化工作
}
}
3.如果希望指定去调用父类的某个构造器,在,则显示的调用一下:super(参数列表)。
4.super在使用时,需要放在构造器的第一行。
5.super()和this()都只能放在构造器的第一行,因此这两个方法不能共存在一个构造器(super只能在构造器中使用)
6.java所有类都是object类的子类,obect是所有类的基类
7.父类构造器的调用不限于直接父类,将一直追溯到object类。(比如说这里的父类的base的父类是object)
8.子类最多只能继承一个父类(指直接继承),即java是单继承机制。
四、super关键字:
super代表父类的引用,用于访问父类的属性、方法、构造器。
- 访问父类的属性,但不能访问父类的private属性 super.属性名
- 访问父类的方法,不能访问父类的private方法。 super.方法名(参数列表)
访问父类的构造器 super(参数列表)
未完...............