1.静态
关键字:static 含义:静态 被static修饰的成分,就是静态的.
静态:不会随对象的变化而变化
加载时机:随着类的加载而加载.
静态变量优先于对象存在
静态变量被所有当前类型对象共享.
访问方式: 静态变量可以通过对象或者类名的方式来访问.
可以通过对象访问,格式:对象名.静态变量名
可以通过静态访问,格式:类名.静态变量名
import example.Person;
public class Static {
String name;
int age;
static String country;
//无参构造
public Static() {
}
//有参数构
public Static(String name, int age) {
this.name = name;
this.age = age;
}
public Static(String name,int age,String country ) {
this.name = name;
this.age = age;
this.country = country;
}
public void show(){
System.out.println("姓名:"+name+",年龄"+age+",国家:"+country);
}
}
class StaticTest{
public static void main(String[] args) {
Person p1 = new Person("貂蝉",25,"中国") ;
p1.show();
Person p2 = new Person("王昭君",22);
p2.show();
Person p3 = new Person("西施",18);
p3.show();
}
}
静态访问的注意事项
1.静态方法不能访问非静态方法/非静态变量.
因为静态方法存在的时候对象很有可能不存在,非静态方法需要对象才可以调用访问.
非静态变量随着对象的创建而创建,所以静态方法不能访问非静态变量.
2.静态方法中不能使用this.
this指代对象,静态优先于对象存在,静态方法要是要去执行,对象可能还没有创建,this指代不到任何内容.
非静态方法既能够访问非静态变量,也能够访问静态变量.
非静态方法能既能够调用非静态方法,也能够调用静态方法.
总结:静态不能访问非静态.
静态方法的调用格式: 1.对象名.静态方法名 2.类名.静态方法名
2.代码块
含义:
使用大括号将一段代码包围起来。根据书写的位置不同,具有不同的名称,不同的作用,及不同的执行时机。
1.
局部代码块
格式:任意一段代码用大括号包围起来
位置:方法中使用.
作用:限定变量的生命周期
构造代码块
位置:类成员位置(类中方法外)
作用:用于执行所有构造方法中共性的内容或者给成员变量赋值
执行时机:在对象创建的过程中,由JVM自动调用,针对每个对象有且仅有一次调用机会。如果仅仅是类加载了,但是没有创建对象,构造代码块是不会执行的
静态代码块
- 格式:
static {
代码段
}
位置:类成员位置
执行特点:
随着类的加载而执行,类只加载一次,所以静态代码块也只加载一次在最初执行,早于所有对象相关的内容.
静态代码块>构造代码块>构造方法
每次执行构造方法之前 优先执行所有的构造代码块 .
class Student{
static{
System.out.println("Student的静态代码块1") ;
}
public Student(){
System.out.println("Student的无参构造方法") ;
}
{
System.out.println("Student的构造代码块1") ;
}
{
System.out.println("Student的构造代码块2") ;
}
public Student(String str){
System.out.println("Student的有参构造方法") ;
}
static{
System.out.println("Student的静态代码块2") ;
}
}
class StudentTest{
static{
System.out.println("高圆圆已经42了,我很伤心") ;
}
public static void main(String[] args){
Student s = new Student() ;
Student s2 = new Student("hello") ;
}
}
}
/*高圆圆已经42了,我很伤心
Student的静态代码块1
Student的静态代码块2
Student的构造代码块1
Student的构造代码块2
Student的无参构造方法
Student的构造代码块1
Student的构造代码块2
Student的有参构造方法
每次执行构造方法之前优先执行所有的构造代码块*/
继承
让类与类之间产生关联,子父的关系
实现继承:使用关键字:extends,含义:继承、增加、扩展
格式:
class 子类名 extends 父类名(){
}
继承的好处和弊端
- 好处:
- 提高了代码的复用性
- 提高了代码的可维护性
- 弊端:
- 提高了代码的耦合性(耦合度)
- 耦合度:代码与代码之间关联的紧密程度
- 开发原则:高内聚,低耦合,代码复用性高
继承的注意事项
1.私有的成员不能被继承
父类中的私有成员,不能在子类中直接使用.
2.父类中的构造方法不能被继承
子类构造访问父类构造,父类构造再去访问父类私有的成员变量,从而达成间接访问
继承的设计:
要符合子类is a父类的逻辑,子类是父类的一种.
/* 南方人和北方人都有姓名,年龄以及性别,职业,都有"吃饭"的功能,但是南方人经常吃米饭,北方人经常吃面条,
南方人主要还去经商,北方人主要考学,请使用继承的实现 使用代码实现(测试的时候使用多态进行测试) */
public class Person {
//姓名,年龄以及性别,职业
private String nama;
private int age;
private String sex;
public Person() {
}
public Person(String nama, int age, String sex) {
this.nama = nama;
this.age = age;
this.sex = sex;
}
public String getNama() {
return nama;
}
public void setNama(String nama) {
this.nama = nama;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void eat() {
System.out.println("吃饭");
}
public void Worker() {
System.out.println("工作");
}
}
class NorthPerson extends Person {
public NorthPerson() {
}
public NorthPerson(String nama, int age, String sex) {
super(nama, age, sex);
}
public void eat() {
System.out.println("喜欢吃面条");
}
public void Worker() {
System.out.println("去经商");
}
}
class SouthPerson extends Person {
public SouthPerson() {
}
public SouthPerson(String nama, int age, String sex) {
super(nama, age, sex);
}
public void eat() {
System.out.println("喜欢吃米饭");
}
public void Worker() {
System.out.println("去考学");
}
}
class PersonTest{
public static void main(String[] args) {
Person p1 = new NorthPerson("李四",25,"男");
System.out.println(p1.getNama()+","+p1.getAge()+","+p1.getSex());
p1.eat();
p1.Worker();
System.out.println("<---------------------------------->");
Person p2 = new SouthPerson("张三",24,"女");
System.out.println(p2.getNama()+","+p2.getAge()+","+p2.getSex());
p2.eat();
p2.Worker();
}
}
Java中继承的特点
Java支持单继承,不支持多继承,支持多层继承.
多层继承:C继承B,B继承A。说明:越是顶层的类,类成员越少,因为都是共性的内容.
public class Extends {
}
//子子孙孙无穷尽也
class A {
public void test() {}
}
class B {
public void test() {}
}
class C extends A {
}
class X {
int num = 10;
}
class Y extends X{
public void test() {
System.out.println(num);
}
}
class Z extends Y {//对于X而言,Z是间接子类,对于Y而言,Z是Y的直接子类
public void show() {
System.out.println(num);
}
}
继承中成员变量的关系
- 在子父类中如果没有定义重名的变量,子类就可以直接使用父类中继承来的变量
- 如果子父类中定义了重名的变量,子类对象就只使用子类成员变量,不会使用父类成员变量
- 当子父类中定义了重名的成员变量时,按照就近原则访问:例如,子类方法中访问一个变量,此时会先在子类方法中寻找该变量的定义,找到直接使用,找不到去本类中找,如果还找不到,就去父类中找,一直往上,直到找到Object类中,还是找不到就会报错。
关键字this和super的详细解释
this关键字:指代当前类型的当前对象的引用
super关键字:指代当前对象的父类的引用.
this和super可以访问的内容:
可以访问成员变量, 可以访问成员方法
this和super都可以访问构造方法.
this();访问本类的其他构造 super();访问父类的指定构造
super:代表父类对象的地址值的引用.
子类访问父类私有成员变量的方式:
子类继承父类私有成员对应的get、set方法,通过get、set进行赋值取值操作.
子类对象在创建的过程中,调用子类的构造方法,自己的构造方法通过super();语句访问父类对应构造,父类构造为自己私有的成员变量赋值,从而达成间接访问.
在继承关系中,构造方法的访问问题
1)子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法
为什么?了类继承父类,会用到父类的数据,因红需要让父类先进行初始化.
子类继承父类子类的构造方法是不能继承父类的构造方法的,但是可以通过关键字
supera来访问父类的构造方法
super(),访阿父类的无参构造方法
super(xox:访问父类的有参构造方法
this():访问自己本类的无参构造方法
this(xxxx):访问自已本来的有参构造方法
子类继承父类,子类的所有构造方法都默认访问父类的无参构造方法,子类的构造方法一般第一句话隐藏:super();
方法重写
产生在子父类的继承关系中
override 子类在父类的基础上,将父类覆盖了,使用自己的功能.(子类体现)
方法重写和方法重载的区别.
重写:子类在父类的基础上,将父类覆盖了,使用自己的功能.(子类体现)
注意:
私有方法不能被重写
静态方法不能被重写
重载;方法定义的时候,方法名相同,参数列表不同,与返回值无关,拓展这个方法的功能.
final关键字
/*
假如我们在开发一个系统时需要对员工类类进行设计,程序员是员工,包含3个属性:姓名、工号以及工资。
经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。
请使用继承的思想设计出程序员类和经理类。要求类中提供必要的方法进行属性访问。 (程序员使用多态进行测试,经理类使用具体类创建对象即可)
*/
abstract class Staff {
//员工类:姓名、工号以及工资
private String name;
private int id;
private double salary;
public Staff() {
}
public Staff(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public abstract void work();
public abstract void rest();
}
class Programmer extends Staff{
public Programmer() {
}
public Programmer(String name, int id, double salary) {
super(name, id, salary);
}
@Override
public void work() {
System.out.println("写代码");
}
@Override
public void rest() {
System.out.println("趴着睡");
}
}
class Manager extends Staff{
private int bonus;
public int getBonus() {
return bonus;
}
public void setBonus(int bonus) {
this.bonus = bonus;
}
public Manager(int bonus) {
this.bonus = bonus;
}
public Manager(String name, int id, double salary, int bonus) {
super(name, id, salary);
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("让程序员写代码");
}
@Override
public void rest() {
System.out.println("床上休息");
}
}
class StaffDemo{
public static void main(String[] args) {
Staff p = new Programmer("张三",8888,8888.8);
System.out.println(p.getName()+"---"+p.getId()+"---"+p.getSalary());
p.work();
Manager m = new Manager("王五",6666,6666.6,1000);
System.out.println(m.getName()+"---"+m.getId()+"---"+m.getSalary()+"----"+m.getBonus());
m.work();
}
}
多态
含义:一个事物在不同时刻体现的不同形态.微观角度(内存中):具体对象在内存中的变化(对象在不同的时刻的类型).
对象的多态性:同一个对象,可能具有不同的名称,可以有不同类型的引用指向他。本质:同一个物对象,有不同的名称和描述。
类的多态性:同一个类型,可能有不同子类的实现。同一个类型的引用,可能会指向不同子类的对象。本质:同一个名字和描述,可能在不同的场景下有不同的实现。
多态的前提条件
1.要有继承关系
2.有方法的重写.子类的部分功能对父类部分功能进行覆盖.重写.子类使用自己的功能体现.
3.存在父类引用指向子类对象.
多态中成员变量的访问特点
父类名 对象名 = new 子类名(); // 父类引用指向子类对象
多态的好处
1.提高代码的复用性,由继承体现.
2.提高代码的拓展性,由多态保证 :父类引用指向子类对象.
多态的弊端:
无法调用子类特有的功能.
解决方案:
1.创建子类具体对象.但是又得重新再堆内存中开辟空间,消耗内存比较大.(不建议)
2.向下转型
前提必须向上转型 必须创建父类对象父类引用指向子类对象.
父类名 父类对象名 = new 子类名(); //向上转型
Zi z = (Zi)fu;
子类名 对象名= (子类名)父类对象://向下转型
package test_01;
/**
* 假如我们在开发一个系统时需要对员工类类进行设计,程序员是员工,包含3个属性:姓名、工号以及工资。
* 经理也是员工,除了含有员工的属性外,另为还有一个奖金属性。
* 请使用继承的思想设计出程序员类和经理类。要求类中提供必要的方法进行属性访问。
* (程序员使用多态进行测试,经理类使用具体类创建对象即可)
*
* 分析:
* 程序员 姓名、工号以及工资
* work()
* 经理 姓名、工号以及工资还有一个奖金属性。
* work()
*
* 共性内容抽取出来-----Employee 员工类
* 姓名、工号以及工资
* work()
*
* 子类 Programmer 程序员
* Manager 经理类
* 继承 Employee
* 重写work()
*
*
*/
public class Test1 {
public static void main(String[] args) {
//经理类:
//无参构造方法+setXXX()/getXXX
Manager manager = new Manager() ;
manager.setName("高圆圆") ;
manager.setEmpId("develop9527") ;
manager.setSalary(8000.00);
manager.setBonus(10000.00);
System.out.println(manager.getName()+"---"+manager.getEmpId()+"---"+manager.getSalary()+"---"+manager.getBonus());
manager.work();
manager.business();
System.out.println("-------------------------------");
//有参构造方法
Manager manager2 = new Manager("赵又廷","develop008",7000.00,1000.00) ;
System.out.println(manager2.getName()+"---"+manager2.getEmpId()+"---"+manager2.getSalary()+"---"+manager2.getBonus());
manager2.work();
manager2.business();
System.out.println("-----------------------------------");
//程序员类: 多态测试
//父类引用指向子类对象 格式
Employee emp = new Programmer("张三丰","test001",8000.00) ; //向上转型
System.out.println(emp.getName()+"---"+emp.getSalary()+"---"+emp.getEmpId());
emp.work(); //编译看左,运行看右
// emp.study() ;
//不能访问子类特有功能
//向下转型
Programmer pro = (Programmer) emp;
pro.study();
}
}
instanceof关键字
instanceof,关键字,是一个运算符,结果是一个布尔类型的结果.
格式:A instanceof B
作用:A是一个对象,B是一个类型。用于判断A对象是否和B类型有关,如果A对象和B类型有关就返回true,否则返回false. 有关:(A对象是B类型的对象,或者是B类型子类的对象)
/**
* 画笔案例
*
* @author Zihuatanejo
*
*/
public class Demo05_Pen {
public static void main(String[] args) {
//Pen b = new Brush();
//Pen b = new DrawPen();
Pen b = new EyePen();
Painter p = new Painter();
p.drawPicture(b);
}
}
/**
* 笔类
*
* @author Zihuatanejo
*
*/
class Pen {
public void write() {
System.out.println("笔画出印记");
}
}
/**
*
* 画笔类
*
* @author Zihuatanejo
*
*/
class Pencile extends Pen {
public void drawing() {
System.out.println("画画");
}
}
/**
* 毛笔类
*
* @author Zihuatanejo
*
*/
class DrawPen extends Pencile {
@Override
public void drawing() {
System.out.println("画中国画");
}
}
/**
* 排笔
*
* @author Zihuatanejo
*
*/
class Brush extends Pencile {
@Override
public void drawing() {
System.out.println("画油画");
}
}
/**
* 眼线笔
*
* @author Zihuatanejo
*
*/
class EyePen extends Pen {
}
/**
* 画家类
*
* @author Zihuatanejo
*
*/
class Painter {
public void drawPicture(Pen p) {//Pen p = new Brush();
//1.判断当前对象是否为画笔类型的对象
if(p instanceof Pencile) {
//2.如果是画笔类对象,就向下转型为画笔,调用画画的方法
Pencile pe = (Pencile)p;//Pencile pe = new Brush();
pe.drawing();
} else {
p.write();
}
}
}
抽象 abstract
抽象方法:
只有方法声明没有具体方法实现的方法,就是抽象方法,额外的在方法的声明上加上abstract关键字,来表示是一个抽象方法.
格式 public abstract 返回值类型 方法名(参数列表);
抽象类
可以定义抽象方法的类就是抽象类(普通的类不能定义抽象方法)
格式: abstract class 类名 {}
抽象类的特点
1.抽象类不能实例化
2.必须强制子类完成事情,将父类抽象方法重写.
2. 抽象类多态 抽象的父类名 对象名 = new 具体的子类名();
抽象类的成员特点:
成员变量 : 可以为变量也可以为final修饰的变量(常量).
成员方法: 抽象方法/非抽象化方法.
构造方法:
无参/有参方法都可以 存在抽象类多态,有继承关系,初始化的时候,构造方法---分层初始化--->(先父类初始化,然后子类初始化).
abstract 和 其他冲突的关键字
和private 冲突. private修饰的方法只能在类访问 ,而abstract 修饰的方法必须要子类的方法重写.
和final 冲突 final修饰的成员方法不能被重写.abstract 强制重写
和static冲突 static方法算不上重写;类名.方法名 调用. abstract修饰的方法类名不能访问.
重写父类的抽象方法的权限问题:
子类继承父类,子类重写父类的抽象方法,必须保证访间权限足够大,要么public要么跟父类的方法保特一致!
/* 编写一个Person抽象类,要求含有姓名(name)年龄(age)两个私有属性以及吃饭(eat)
和睡觉(sleep)两个抽象方法,并写出带参构造方法,
创建学生(student)和工人(worker) 两个类,继承Person类,
学生类多出了私有属性学号和学习方法(输出我爱学习),
工 人类多出了私有属性工号和工作方法(输出我爱工作) */
abstract class Person {
private String name;
private int age;
public Person() {
}
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 Person(String name, int age) {
this.name = name;
this.age = age;
}
public abstract void eat();
public abstract void sleep();
}
class Student extends Person{
public Student() {
}
public Student(String name, int age) {
super(name, age);
}
//私有属性学号和学习方法
private String UserId;
public Student(String name, int age, String userId) {
super(name, age);
UserId = userId;
}
public String getUserId() {
return UserId;
}
public void setUserId(String userId) {
UserId = userId;
}
@Override
public void eat() {
System.out.println("吃快餐");
}
@Override
public void sleep() {
System.out.println("住在家里");
}
}
class worker extends Person{
public worker() {
}
public worker(String name, int age) {
super(name, age);
}
public String getWorkId() {
return WorkId;
}
public void setWorkId(String workId) {
WorkId = workId;
}
//私有属性工号和工作方法
private String WorkId;
public worker(String workId) {
WorkId = workId;
}
public worker(String name, int age, String workId) {
super(name, age);
WorkId = workId;
}
@Override
public void eat(){
System.out.println("吃米饭");
}
@Override
public void sleep() {
System.out.println("睡在工地");
}
}
class PersonTest {
public static void main(String[] args) {
Student p1 = new Student("高圆圆", 25, "U12345");
System.out.println(p1.getAge() + "," + p1.getName() + "," + p1.getUserId());
p1.eat();
p1.sleep();
System.out.println("-----------------------------------------");
worker w2 = new worker("张三",18,"W789") ;
System.out.println(w2.getAge() + "," + w2.getName() + "," +w2.getWorkId());
w2.eat();
w2.sleep();
}
}
接口
定义格式:使用关键字interface声明,一个接口编译过后也会生成一个独立的.class文件
interface 接口名 {
}
接口中,只能声明定义抽象方法,不能定义有方法实现的方法.
接口不能实例化,不能创建对象
接口的实现:使用类,通过implements关键字来实现接口.
格式:class 类名 implements 接口名 {}
接口中成员的特点
成员变量:没有,
构造方法:没有,
成员方法:只能是抽象方法,不能是非抽象方法。方法的声明可以省略public abstract
类与类、类与接口、接口与接口之间的关系
类与类:继承关系,使用extends关键字。支持单继承,不支持多继承,支持多层继承
类与接口:实现关系,使用implements关键字
接口与接口:继承关系,使用extends关键字,支持单继承,支持多继承,支持多层继承
抽象类和接口的区别?
成员变量: 抽象类:可以是变量,也可以是自定义常量
接口: 成员变量只能是常量.
成员方法 :抽象类: 抽象方法/非抽象方法
接口:只能是抽象方法
构造方法: 抽象类 :无参构造,有参构造都可以存在 存在继承关系,分层初始化
接口:无构造方法.
抽象类用 entends 接口用implements
package interface_02;
/*
* 会跳高的猫 继承/接口
*
* */
interface jump{
void jump();
}
abstract class Animal{
private String name;
private int age;
private String color;
public Animal() {
}
public Animal(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
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 getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public abstract void eat();
public abstract void sleep();
}
class Cat extends Animal {
public Cat() {
}
public Cat(String name, int age, String color) {
super(name, age, color);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫躺着睡");
}
private void CatchMouse(){
System.out.println("猫抓老鼠");
}
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头");
}
public Dog() {
}
public Dog(String name, int age, String color) {
super(name, age, color);
}
@Override
public void sleep() {
System.out.println("狗趴着睡");
}
private void LookDoor(){
System.out.println("狗看门");
}
}
class JumpCat extends Cat implements jump{
public JumpCat() {
}
public JumpCat(String name, int age, String color) {
super(name, age, color);
}
@Override
public void jump() {
System.out.println("会跳的猫");
}
}
class JumpDog extends Dog implements jump{
public JumpDog() {
}
public JumpDog(String name, int age, String color) {
super(name, age, color);
}
@Override
public void jump() {
System.out.println("会跳的狗");
}
}
public class AnimalTest {
public static void main(String[] args) {
JumpDog dog = new JumpDog("边牧",5,"黑色");
System.out.println(dog.getName()+","+dog.getAge()+","+dog.getColor());
dog.eat();
dog.sleep();
dog.jump();
JumpCat cat = new JumpCat("叮当猫",4,"黑白色");
System.out.println(cat.getName()+","+cat.getAge()+","+cat.getColor());
cat.eat();
cat.sleep();
cat.jump();
}
}