Java 封装、继承、多态
程序员文章站
2024-03-16 23:31:46
...
封装
将类的部分信息隐藏在类内,通过提供的固定方法访问。
访问修饰符
访问修饰符 | 本类 | 同包 | 字类 | 其他 |
---|---|---|---|---|
private | √ | |||
默认 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
this
this.属性名 用来区*部变量和成员变量
private String name;
private int age;
Student(String name , int age){
this.name = name ;
this.age = age;
}
//但是如果写成name=name,就并没有把name赋给Student
this.方法名 用来访问本类的成员方法
this() 访问本类的构造方法,必须放在第一条语句(如果放在最后,会覆盖前面的)
内部类
①成员内部类
原文链接:https://blog.csdn.net/weixin_42762133/article/details/82890555
//每个内部类都可以独立的继承一个接口的实现,无论外部类是否已经继承了某个接口的实现,对内部类没有影响。
public class Outer entends ClassA implements FunctionA{
public class Inner extends ClassB implements FunctionB{
}
}
//当内部类属性名和外部类属性名相同时,注意怎样从内部访问外部类属性
//当外部类要访问内部类,则新建方法,在方法里面new内部类对象,通过对象访问
/**
* 外部类、成员内部类的定义
*/
public class Outer {
private int outerVariable = 1;
private int commonVariable = 2;
private static int outerStaticVariable = 3;
//省略getter/setter
/**
* 成员方法
*/
public void outerMethod() {
System.out.println("我是外部类的outerMethod方法");
}
/**
* 静态方法
*/
public static void outerStaticMethod() {
System.out.println("我是外部类的outerStaticMethod静态方法");
}
/**
* 内部类
*/
public class Inner {
private int commonVariable = 20;
/**
* 构造方法
*/
public Inner() {
}
/**
* 成员方法,访问外部类信息(属性、方法)
*/
public void innerShow() {
//当和外部类冲突时,直接引用属性名,是内部类的成员属性
System.out.println("内部的commonVariable:" + commonVariable);
//内部类访问外部属性
System.out.println("outerVariable:" + outerVariable);
//当和外部类属性名重叠时,可通过外部类名.this.属性名
System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
System.out.println("outerStaticVariable:" + outerStaticVariable);
//访问外部类的方法
outerMethod();
outerStaticMethod();
}
}
/**
* 外部类访问内部类信息
*/
public void outerShow() {
Inner inner = new Inner();
inner.innerShow();
}
}
//在其他类中,创建外部类对象,通过外部类创造内部类对象
/*
* 其他类使用成员内部类
*/
public class Other {
public static void main(String[] args) {
//外部类对象
Outer outer = new Outer();
//创造内部类对象
Outer.Inner inner = outer.new Inner();
inner.innerShow();
/*
* 可在Outer中定义get方法,获得Inner对象,那么使用时,只需outer.getInnerInstance()即可。
* public Inner getInnerInstance(Inner类的构造方法参数){
* return new Inner(参数);
* }
*/
}
}
②静态内部类
//静态内部类的方法只能访问外部类的static关联的信息。
//访问内部类的静态信息,直接外部类.内部类.静态信息就可以了。
//静态内部类可以独立存在,不依赖于其他外围类。
public class Outer {
static {
System.out.println("Outer的静态块被执行了……");
}
public static class Inner {
public void innerShow() {
System.out.println("innerVariable:" + innerVariable);
System.out.println("内部的commonVariable:" + commonVariable);
System.out.println("outerStaticVariable:"+outerStaticVariable);
outerStaticMethod();
}
public static void innerStaticShow() {
//被调用时会先加载Outer类
outerStaticMethod();
System.out.println("outerStaticVariable"+outerStaticVariable);
}
}
}
③局部内部类
//类前不能有访问修饰符。
//仅在方法内使用。
//可以直接访问方法内的局部变量和参数但是不能更改。
//可以随意的访问外部类的任何信息。
public class Outer{
private int outa = 1;
public void outerMethod(){
System.out.println("我是外部类的outerMethod方法")
}
public void outerCreatMethod(int value) {
class Inner{
private int innerVariable = 10;
private int commonVariable = 20;
/**
* 局部内部类方法
*/
public void innerShow() {
System.out.println("innerVariable:" + innerVariable);
//调用外部类的信息
System.out.println("outerVariable:" + outerVariable);
System.out.println("内部的commonVariable:" + commonVariable);
System.out.println("外部的commonVariable:" + Outer.this.commonVariable);
System.out.println("outerStaticVariable:" + outerStaticVariable);
outerMethod();
outerStaticMethod();
}
}
}
//入口
public static void main(String[] args) {
Outer outer = new Outer();
outer.outerCreatMethod(100);
}
}
④匿名内部类
/**
* 定义接口
* 接口中方法默认为public
*/
public interface IAnimal{
void speak();
}
/**
* 外部内、内部类
*/
public class Outer {
public static IAnimal getInnerInstance(String speak){
return new IAnimal(){
@Override
public void speak(){
System.out.println(speak);
}};
//注意上一行的分号必须有
}
public static void main(String[] args){
//调用的speak()是重写后的speak方法。
Outer.getInnerInstance("小狗汪汪汪!").speak();
}
}
继承
特性:
- 子类拥有父类非private的属性、方法
- 子类可以对父类扩展
- 子类可用自己的方式实现父类的方法
- Java可以多重继承,但是是单继承
- 提高了类之间的耦合性
关键字
- extends
- implements
//可以间接实现多继承的特性
public interface A{}
public interface B{}
public class C implements A,B{}
- super与this
this.function();//调用自己的方法
super.function();//调用父类的方法
- final
//可以把类定义为不能继承的,即最终类;或者用于修饰方法,但是该方法不能被子类重写
final class 类名{}
构造器
原文链接:https://blog.csdn.net/li_jeremy/article/details/79294699
- 创建构造器的规则
①构造函数名和类名相同
②构造函数没有显式返回值 - 构造函数类型
//无参数
//显示默认值的默认构造函数
class Student3 {
int id;
String name;
void display() {
System.out.println(id + " " + name);
}
public static void main(String args[]) {
Student3 s1 = new Student3();
Student3 s2 = new Student3();
s1.display();
s2.display();
}
}
//输出结果有值为0 null ,编译器自动提供默认构造函数,它为id和name分别提供了0和null。
//有参数
class Student4 {
int id;
String name;
Student4(int i, String n) {
id = i;
name = n;
}
void display() {
System.out.println(id + " " + name);
}
public static void main(String args[]) {
Student4 s1 = new Student4(111, "Karan");
Student4 s2 = new Student4(222, "Aryan");
s1.display();
s2.display();
}
}
- 构造函数重载
Student5(int i, String n) {
id = i;
name = n;
}
Student5(int i, String n, int a) { //通过参数的不同告知编译器此处用到了构造函数的重载
id = i;
name = n;
age = a;
}
- 拷贝构造函数
//通过构造函数
Student6(int i, String n) {
id = i;
name = n;
}
Student6(Student6 s) { //参数传入的是类对象
id = s.id;
name = s.name;
}
public static void main(String args[]) {
Student6 s1 = new Student6(111, "Karan");
Student6 s2 = new Student6(s1); //将上面的s1传入
}
//将对象值分配给另一个对象
Student7(int i, String n) {
id = i;
name = n;
}
Student7() {}
public static void main(String args[]) {
Student7 s1 = new Student7(111, "Karan");
Student7 s2 = new Student7();
s2.id = s1.id; //直接赋值
s2.name = s1.name;
}
Object类
Object类是所有类的父类,其中的方法适合所有子类
- toString()
- equals()
多态
原文链接:https://www.runoob.com/java/java-polymorphism.html
优点
- 消除类型之间的耦合关系
- 可替换性
- 可扩充性
- 接口性
- 灵活性
- 简化性
三个必要条件
- 继承
- 重写
- 父类引用指向子类对象
//使程序有良好的扩展,并可以对所有类的对象进行通用处理
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
} else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
- 重写
//当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法
//若要调用父类中被重写的方法,必须使用关键字super
多态的实现方式
重写
原文链接:https://www.runoob.com/java/java-override-overload.html
//必须是重写父类已有的方法
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
System.out.println("狗可以跑和走");
}
public void bark(){
System.out.println("狗可以吠叫");
}
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal 对象
Animal b = new Dog(); // Dog 对象
a.move();// 执行 Animal 类的方法
b.move();//执行 Dog 类的方法
b.bark(); /////////////////////////bark在父类里面并没有,报错
}
}
重写规则:
- 参数列表必须完全与被重写方法的相同
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类
- 访问权限不能比父类中被重写的方法的访问权限更低
- 声明为 final 的方法不能被重写
- 声明为 static 的方法不能被重写,但是能够被再次声明
- 构造方法不能被重写
- 如果不能继承一个方法,则不能重写这个方法
重载
被重载的方法必须改变参数列表(参数个数或类型不一样)
public String test(int a,String s){
System.out.println("test3");
return "returntest3";
}
public String test(String s,int a){
System.out.println("test4");
return "returntest4";
}
接口
除非实现接口的是抽象方法,否则要实现接口中的所有方法
抽象类和抽象方法
抽象类:一个类中没有包含足够的信息来描绘一个具体的对象
抽象方法:方法的具体实现又子类确定