继承
代码复用,更容易实现类的扩展;更方便建模;
一个类包含属性、方法、构造方法,继承可以继承父类的所有属性、方法(不包含构造方法),但不能访问父类的私有属性和方法;
类默认继承Object类;
java类只能单继承,接口可以多继承;
子类与父类,方法名、形参列表相同;
子类返回值类型应小于等于父类;(void)
子类的权限应大于等于父类;(public)
final
修饰变量,则不可以在改变;
修饰方法,则子类不能重写,只能重载(不同的方法使用相同的方法名,参数数量不同 参数类型不全同);
修饰类,该类不允许在被继承;
组合
也可以实现代码复用,在一个类里定义个属性为另一个类;
is关系:用继承,如学生是人,学生用人里的属性
has关系:用组合,如笔记本用芯片里的属性
==、equals、super
package com.bhzt.threefeature;
/**
* Ctrl+鼠标左键:追踪源码
* Alt+7:Structure 类结构图
*/
public class Person extends Object /*不写则默认 extends Object*/ {
public String name;
public int height;
public void rest()
{
System.out.println("休息");
}
public Person(){
System.out.println("person 构造方法");
}
}
package com.bhzt.threefeature;
/**
* 继承
* @author puhome
*
*/
public/*子类的权限应大于等于父类*/ class Student extends Person {
public int age;
/**
* 重写
*/
public void/*子类返回值类型应小于等于父类*/ rest()
{
super.rest();//调用父类的方法
System.out.println("学生休息");
}
public Student(String name,int height,int age){
this.name=name;
this.height=height;
this.age=age;
}
/**
* 打印信息
*/
public void printText(){
System.out.println(this.name);
System.out.println(this.height);
System.out.println(this.age);
}
public Student(){
//默认会调用 super();
System.out.println("student 构造方法");
}
}
/**
* 组合
* @author puhome
*
*/
class Student2 {
Person p=new Person();
}
package com.bhzt.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.bhzt.threefeature.Person;
import com.bhzt.threefeature.Student;
class ThreeFeatureTest {
@Test
void personTest()
{
Student s1=new Student("zhangsan",180,20);
boolean b;
if (s1 instanceof Person) { //s1对象是否属于Person类
b=true;
}
else
{
b=false;
}
System.out.println(s1.name);
System.out.println(b);
s1.rest();
}
@Test
void personTestTwo()
{
int n1=0;
int n2=0;
Student s1=new Student("zhangsan",180,20);
Student s2=new Student("zhangsan",180,20);
String t1="123";
String t2="123";
System.out.println(t1);
System.out.println(n1==n2);//True 比较的是值是否相等
System.out.println(s1==s2);//false 比较的是对象地址是否一致
System.out.println(t1==t2);// 比较的是对象地址是否一致
System.out.println(s1.equals(s2));//false 比较的是对象,Object.equals
System.out.println(t1.equals(t2));//True String 类重写了equals方法,比较的是值
//---------------------------------------------------------------------------------
System.out.println("-----------------------------------------------------------------");
//变量放到栈,对象放到堆
String str1="456";
String str2=new String("456");
String str3=str2;
String str4="456";
System.out.println(str1==str2);//对象地址不一样
System.out.println(str1==str4);//对象地址一样
System.out.println(str2==str3);//对象地址一样
}
@Test
void superTest()
{
Student s1=new Student();//构造方法中 会默认调用父类的构造方法
}
}
封装
高内聚 低耦合
高内聚:封装细节,便于修改内部代码,提高可维护性
低耦合:简化外部调用,便于调用者使用,便于扩展和协作
访问限制修饰符
修饰符 | 同一个类 | 同一个包 | 子类 | 所有类 |
---|---|---|---|---|
private | √ | |||
default(默认没有) | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
default:只能邻居用,即使是儿子 不是邻居也不能用
protected:邻居能用,儿子即使不是邻居也能用,但有一点,儿子如果不是邻居(不在同一包) 则不能访问父类对象的成员方法
package com.bhzt.encapsulation;
public class Person {
protected int testProtected=100;
}
package com.bhzt.encapsulationTwo;
import com.bhzt.encapsulation.Person;
public class Teacher extends Person {
void test1()
{
Person p=new Person();
//System.out.println(p.testProtected);//不同包,子类不能访问父类对象的protected 成员
}
void test2()
{
System.out.println(super.testProtected);//不同包,子类可以用此方式访问父类对象的protected成员
}
}
经验总结:
属性都用private修饰,在提供相应的访问方法用public修饰;
JavaBean
package com.bhzt.encapsulation;
/**
* 选中待封装属性,Refactor/Encapsulation Fields
* 一个简单的JavaBean
*/
public class Person {
protected int testProtected=100;
private String name;
private int age;
private boolean flag;
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 boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
多态
多态,指同一个方法调用,由于对象不同可能会有不同的行为。
1.多态是方法的多态,与属性无关
2.多态存在的3个条件,继承、方法重写、父类引用指向子类对象
3.父类引用指向子类对象后,用该父类引用调用子类重写的方法
package com.bhzt.polymorphism;
public class Animal {
public void shout(){
System.out.println("发出声音");
}
}
package com.bhzt.polymorphism;
public class Cat extends Animal {
@Override
public void shout() {
System.out.println("喵喵喵");
}
public void seePark(){
System.out.println("猫看院");
}
}
package com.bhzt.polymorphism;
public class Dog extends Animal {
@Override
public void shout() {
System.out.println("汪汪汪");
}
public void seeDoor()
{
System.out.println("狗看门");
}
}
package com.bhzt.polymorphism;
public class ShoutAll {
// public static void startShoutDog(Dog animal)
// {
// animal.shout();//如果不用多态,则每增加一个动物,都需要重载一次
// }
// public static void startShoutCat(Cat animal)
// {
// animal.shout();//如果不用多态,则每增加一个动物,都需要重载一次
// }
public static void startShout(Animal animal)
{
animal.shout();//多态,如果不用多态,则每增加一个动物,都需要重载一次
}
}
package com.bhzt.test;
import com.bhzt.polymorphism.Animal;
import com.bhzt.polymorphism.Cat;
import com.bhzt.polymorphism.Dog;
import com.bhzt.polymorphism.ShoutAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* 多态
*/
class PolyTest {
@Test
public void shoutTest()
{
Animal a1=new Dog();//父类引用子类对象
ShoutAll.startShout(a1);
Cat c1=new Cat();
ShoutAll.startShout(c1);//父类引用子类对象
//类型转换----------------------------
Animal a2=new Dog();//向上类型转换,自动转,Dog 转 Animal
//a2.seeDoor();Dog里的自定义方法 不能直接调用
// Dog d2=(Dog) a2;//向下强制转换,Animal转Dog
// d2.seeDoor();
if(a2 instanceof Dog) {
Dog d2 = (Dog) a2;//向下强制转换,Animal转Dog
d2.seeDoor();
}
//Cat c2=(Cat)a2;
//c2.seePark();//编译能通过,但执行会异常
}
}