封装
首先了解一下封装的概念:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现读隐藏信息的操作和访问,把尽可能多的东西藏起来,对外提供便捷的接口。
为什么使用封装
看下方示例:
Student student = new Student();
student.age = -100;
在上述例子中,由于未对属性进行封装,用户可随意对属性赋值,很明显年龄负数是不合理的
如何实现封装
①修改属性的可见性:设为private,防止错误的修改
②创建共有的getter和setter方法:用于属性的读写
③在getter和setter方法中加入属性控制语句:对属性值的合法性进行判断
// 上述例子可修改
public class Student(){
private int age = 20;
public void setAge(int age){
if(age<0||age>100){
System.out.println("输入有误,默认年龄为20岁");
return;
}
this.name = name;
}
public int getAge() {
return age;
}
}
封装的好处
①便于使用者正确使用系统,防止错误修改属性
②有助于系统之间的松耦合,提高系统独立性
③提高软件的可重用性
④降低了构建大型系统的风险
访问修饰符
在封装时,我们用到了private修饰符,在之前的学习中我们最常见的是public,java的访问修饰符有四种,按照作用域大小分,从大到小依次为
public、protected、缺省的、private
static修饰符
修饰属性时:全类共用一个存储空间
普通属性:一个对象用一个存储空间
修饰方法时:可以通过类名.方法名()调用
普通方法可以直接调用静态方法和普通方法
静态方法不能直接调用普通方法
普通方法可以直接调用普通方法和静态属性
静态方法不能直接调用普通属性
静态代码块:
只在第一次访问该类时执行一次,且只执行这一次
public class Demo {
public static int a = 1;
int b = 2;
static {
//在第一次访问该类时(在创建对象之前)执行,且只执行一次
System.out.println("静态代码块");
}
public Demo(){
System.out.println("无参构造");
}
public void test(){
a++;//普通方法可以看到静态属性
b++;// 普通方法可以看到普通属性
abc();//普通方法可以直接调用静态方法
}
public static void abc(){
// 静态方法中看不到普通属性和普通方法
//test();编译错误
//b++;编译错误
//a++;编译通过
}
}
// TestDemo类
public class Test {
public static void main(String[] args) {
Demo demo = new Demo();
System.out.println(demo.b);
System.out.println(Demo.a);
Demo.abc();//在不同类中,可以直接用类名.静态方法名(),直接调用
Demo demo1 = new Demo();
/**结果输出
* 静态代码块
* 无参构造
* 2
* 1
* 无参构造
* /
}
}
实例:
// 选民投票,票数大于100停止
// Vote类
public class Vote {
public static int voteNum = 0;
public static void vote(){
voteNum++;
}
}
// TestVote类
public class TestVote {
public static void main(String[] args) {
for (int i = 1; i <= 200 ; i++) {
Vote.vote();
System.out.println("当前票数:"+Vote.voteNum);
if(Vote.voteNum>=100){
System.out.println("投票完成!");
break;
}
}
}
}
继承
当我们需要写一个猫类和狗类时,由于猫、狗都具有姓名、体重、性别等属性,那么会存在大量的代码冗余,为了减少代码冗余,我们可以将猫、狗具有的共同属性、方法抽离到一个动物类,猫狗作为子类,动物作为父类,像猫狗与动物的种关系就是is-a关系。
如何使用继承
①编写父类
[访问修饰符]class 父类名{
// 公共属性和方法
}
②编写子类,继承父类
[访问修饰符] class 子类名 extends 父类名{
//子类特有的属性和方法
}
需要注意的是:继承是java实现代码重用的重要手段之一。java中只支持单根继承,即一个类只能有一个直接父类
super关键字
作用:
①访问父类构造方法:super();super(name);
②访问父类属性:super.name;
③访问父类方法:super.print();
注意点:
①使用super关键字,super代表父类对象
②在子类构造方法中调用且必须是第一句
③不可以访问父类定义为private的属性和方法
继承条件下构造方法的调用规则
①子类构造方法没有通过super显式调用父类的有参构造方法,也没通过this显式调用自身其他构造方法:系统默认调用父类的无参构造方法
②子类构造方法通过super显式调用父类的有参构造方法:执行父类相应构造方法,而不执行父类无参构造方法
③子类构造方法通过this显式调用自身的其他构造方法,在相应构造方法中应用以上两条规则
示例
// 父类
public class A(){
public A(){
System.out.println("父类无参构造方法");
}
public A(int age){
System.out.println("父类有参构造方法");
}
}
// 子类
public class B extends A(){
public B(){
System.out.println("子类无参构造方法");
}
public B(int age){
super(age);
System.out.println("子类一个参数构造方法");
}
public B(int age,int num){
this();
System.out.println("子类两个参数构造方法");
}
}
// Test类
public class Test(){
public static void main(String[] args) {
B b = new B();
B b1 = new B(1);
B b2 = new B(1,1);
}
}
在使用继承时,要注意:子类继承父类所有,父类私有的东西,也继承了,只是看不到。子类创建对象时,会先执行父类的无参构造方法,在执行子类的构造方法