一、static
1. 静态变量
特点
被该类所有对象公用
不属于对象,属于类
随着类的加载而加载,优先于对象出现
调用方式
类名调用(推荐)、对象名调用
例子
package staticdemo1;
public class StudentTest {
public static void main(String[] args) {
Student.teacherName = "王老师";
Student s1 = new Student();
s1.setName("张三");
s1.setAge(20);
s1.setGender("男");
// s1.teacherName = "王老师";
s1.show();
s1.study();
Student s2 = new Student("李四", 21, "女");
s2.show();
s2.study();
Student s3 = new Student("王五", 22, "男");
s3.show();
s3.study();
}
}
package staticdemo1;
public class Student {
private String name;
private int age;
private String gender;
// public String teacherName;
public static String teacherName;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public void study() {
System.out.println(name + " 正在学习.");
}
public void show(){
System.out.println(name + ","+age+","+gender+","+teacherName);
}
}
2. 静态方法
特点
多用在测试类和工具类中, JavaBean类中很少会用
调用方式
类名调用(推荐)、对象名调用
3. 工具类
简单介绍
JavaBean类 | 用于描述一类事物的类 比如Student、Cat等 |
测试类 | 用来检查其他类是否书写正确 带有main方法的类,是程序的入口 |
工具类 | 用来帮我们做一些事情的类 |
私有化构造方法,目的是为了不让外界创建其对象
方法定义为静态
例子1
数组的打印和求平均
package staticdemo2;
public class ArrayUtil {
//私有化构造方法
private ArrayUtil() {
}
public static String printArray(int[] arr) {
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
sb.append(arr[i]);
}else{
sb.append(arr[i] + ",");
}
}
sb.append("]");
return sb.toString();
}
public static double getAverage(double[] arr) {
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum / arr.length;
}
}
package staticdemo2;
public class TestDemo { // 测试类
public static void main(String[] args) {
//测试工具类中的两个方法是否正确
int[] arr = {1, 2, 3, 4, 5};
String str = ArrayUtil.printArray(arr);
System.out.println(str);
double[] arr1 = {1.1, 2.2, 3.3, 4.4, 5.5};
double avg = ArrayUtil.getAverage(arr1);
System.out.println(avg);
}
}
例子2
学生工具列,获取集合中最大年龄
package staticdemo1;
public class Student {
private String name;
private int age;
private String gender;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
package staticdemo1;
import java.util.ArrayList;
public class StudentTool {
private StudentTool() {}
public static int getMaxAgeStudent(ArrayList<Student> list) {
int maxAge = list.get(0).getAge();
for (int i = 1; i < list.size(); i++) {
int tempAge = list.get(i).getAge();
if (tempAge > maxAge) {
maxAge = tempAge;
}
}
return maxAge;
}
}
package staticdemo1;
import java.util.ArrayList;
public class StudentTest {
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>();
Student s1 = new Student("zhangsan", 18, "male");
Student s2 = new Student("lisi", 19, "female");
Student s3 = new Student("wangwu", 20, "male");
list.add(s1);
list.add(s2);
list.add(s3);
//调用工具类中的方法
int maxAge = StudentTool.getMaxAgeStudent(list);
System.out.println("最大年龄为:" + maxAge);
}
}
4. static的注意事项
内容
静态方法只能访问静态
非静态方法可访问所有
静态方法中没有this关键字(隐含)
代码解释、内存解释
听麻了,脑子不转了,就记住有上面三个注意事项吧
5. 重新认识main方法
public | 被JVM调用,访问权限足够大 |
static | 被JVM调用,不用创建对象,直接类名访问 main是静态,所以测试类里的方法都得是静态 |
void | 被JVM调用,不需要给JVM返回值 |
main | 一个通用名称,不是关键字,可被JVM识别 |
String[] args | 现在没用,以前用于接收键盘录入数据,现在用scanner |
二、继承
1. 基础内容
面向对象三大特征:封装、继承、多态
继承:关键字extends可以让两个类建立继承关系,即基类、派生类
格式:public class 基类 extends 派生类{ }
特点:Java只支持单继承、不支持多继承、但支持多层继承
每一个类都直接或间接地继承于Object
派生类只能访问基类中非私有的成员
使用继承的好处:提高代码的复用性、在基类的基础上增强更多功能
2. 练习
可用画图法理清继承关系,画图从下往上画,写代码时从上往下写(上是基类,下是派生类)
package oopextendsdemo1;
public class Animal {
//权限修饰符,不是public而是private的话只能在本类中访问
public void eat() {
System.out.println("吃东西");
}
public void drink() {
System.out.println("喝水");
}
}
package oopextendsdemo1;
public class Cat extends Animal {
public void catchMouse() {
System.out.println("猫抓老鼠");
}
}
package oopextendsdemo1;
public class Dog extends Animal {
public void lookHome() {
System.out.println("狗看家");
}
}
package oopextendsdemo1;
public class Ragdoll extends Cat {
}
package oopextendsdemo1;
public class LiHua extends Cat{
}
package oopextendsdemo1;
public class Husky extends Dog{
public void breakHome() {
System.out.println("哈士奇拆家");
}
}
package oopextendsdemo1;
public class Teddy extends Dog {
public void touch(){
System.out.println("泰迪又在蹭我的腿了~");
}
}
package oopextendsdemo1;
public class Test {
public static void main(String[] args) {
//1. 创建布偶猫对象
Ragdoll rd = new Ragdoll();
rd.eat();
rd.drink();
rd.catchMouse();
System.out.println("======================");
//2. 创建哈士奇对象
Husky hs = new Husky();
hs.eat();
hs.drink();
hs.lookHome();
hs.breakHome();
}
}
3. 派生类能继承基类中的哪些内容
表格总结
public(其他的非私有同理) | private | |
构造方法 | NO | NO |
成员变量 | YES | YES |
成员方法 | 虚方法YES | 非虚方法NO |
构造方法:违背了构造方法的名字和类名(class)不一致
成员变量:private是继承了但不能直接使用
成员方法:只有基类的虚方法才能被派生类继承
虚方法表:将经常使用的方法单独放置,非private、非static、非final。每一个基类都会将自己的虚方法表传给派生类,派生类会在此基础上进行添加。
误区
基类私有的东西,派生类就无法继承
基类非私有的东西,就被派生类继承下来
4. 继承中的访问特点
成员变量的访问特点
就近原则:谁离得近,就用谁。先在局部位置找,本类成员位置找,父类成员位置找,逐级进行
重名的成员变量:
System.out.println(name);// 从局部开始往上找 System.out.println(this.name);// 从本类成员位置开始往上找 System.out.println(super.name);// 从基类成员位置开始往上找
package oopextendsdemo1;
public class Test {
public static void main(String[] args) {
Nv n = new Nv();
n.nvShow();
}
}
class Mu{
String name = "Mu";
}
class Nv extends Mu{
String name = "Nv";
public void nvShow(){
String name = "nvshow";
System.out.println(name);
System.out.println(this.name);
System.out.println(super.name);
}
}
成员方法的访问特点
就近原则、super调用访问基类
和成员变量是一样的的逻辑,不同点在于成员方法只有两个即this(本类)和super(基类)
package oopextendsdemo1;
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.lunch();
System.out.println("=======================");
OverseaStudents os = new OverseaStudents();
os.lunch();
}
}
class Person{
public void eat(){
System.out.println("吃米饭、吃菜");
}
public void drink(){
System.out.println("喝开水");
}
}
class OverseaStudents extends Person{
public void lunch(){
this.eat();
this.drink();
super.eat();
super.drink();
}
@Override
public void eat(){
System.out.println("吃意大利面、吃意大利菜");
}
@Override
public void drink(){
System.out.println("喝凉水");
}
}
class Student extends Person{
public void lunch(){
this.eat();
this.drink();
super.eat();
super.drink();
}
}
方法重写
方法的重写:当基类不满足派生类的需求时,使用一模一样的方法声明
@Override是放在重写方法上,校验语法是否正确
本质是覆盖了虚方法表中的方法
方法重写的注意事项:重写的方法尽量和基类一致,名称、形参列表必须一致
只有被添加到虚方法表中的方法才能被重写
方法重写时,访问权限派生类>基类,返回值类型派生类<基类
方法重写练习
package oopextendsdemo1;
public class Dog {
public void eat() {
System.out.println("狗在吃狗粮");
}
public void drink() {
System.out.println("狗在喝水");
}
public void lookHome() {
System.out.println("狗在看家");
}
}
package oopextendsdemo1;
public class Husky extends Dog{
public void breakHome() {
System.out.println("哈士奇拆家");
}
}
package oopextendsdemo1;
public class ShaPi extends Dog{
@Override
public void eat() {
super.eat(); //System.out.println("沙皮在吃狗粮");
System.out.println("狗啃骨头");
}
}
package oopextendsdemo1;
public class ChineseDog extends Dog {
@Override
public void eat() {
System.out.println("中犬在吃剩饭");
}
}
package oopextendsdemo1;
public class Test {
public static void main(String[] args) {
Husky h = new Husky();
h.eat();
h.drink();
h.lookHome();
h.breakHome();
System.out.println("--------------------");
ShaPi s = new ShaPi();
s.eat();
s.drink();
s.lookHome();
System.out.println("--------------------");
ChineseDog c = new ChineseDog();
c.eat();
c.drink();
c.lookHome();
}
}
构造方法的特点
基类的构造方法是不能被派生类继承
无参
派生类中所有构造方法默认先访问基类的无参构造,再执行自己的
派生类构造方法的第一行有默认的super()
(派生类初始化前,一定要调用基类构造方法先完成其数据空间的初始化)
package oopextendsdemo2;
public class Person {
String name;
int age;
public Person() {
System.out.println("基类的无参构造");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
package oopextendsdemo2;
public class Student extends Person {
public Student() {
//派生类构造方法中隐藏的super()去访问基类的无参构造
super();
System.out.println("派生类的无参构造");
}
}
package oopextendsdemo2;
public class Test {
public static void main(String[] args) {
Student s = new Student();
}
}
有参
手动写super进行基类有参构造调用
person同上
package oopextendsdemo2;
public class Student extends Person {
public Student() {
//派生类构造方法中隐藏的super()去访问基类的无参构造
super();
System.out.println("派生类的无参构造");
}
public Student(String name, int age) {
super(name, age);
}
}
package oopextendsdemo2;
public class Test {
public static void main(String[] args) {
Student s = new Student("zhagnsan", 20);
System.out.println(s.name+","+s.age);
}
5. this、super使用总结
this:表示当前方法调用者的地址值
super:代表基类存储空间
访问成员变量 | 访问成员方法 | 访问构造方法 | |
this | this.成员变量 访问本类成员变量 | this.成员方法(...) 访问本类成员方法 | this(...) 访问本类构造方法 |
super | super.成员变量 访问基类成员变量 | super.成员方法(...) 访问基类成员方法 | super(...) 访问基类构造方法 |
this(...)一般在需要给默认值的场景下使用
package oopextendsdemo2;
public class Student {
String name;
int age;
String school;
public Student() {
//表示调用本类其他构造方法
//细节:虚拟机就不会再添加super()了
this(null,0,"传智教育");
}
public Student(String name, int age, String school) {
this.name = name;
this.age = age;
this.school = school;
}
}
package oopextendsdemo2;
public class Test {
public static void main(String[] args) {
Student s = new Student();
System.out.println(s.name+","+s.age);
}
}
6. 练习-带有继承结构的标准JavaBean类
package oopextendsdemo3;
public class Employee {
private String id;
private String name;
private double salary;
public Employee() {}
public Employee(String id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void work() {
System.out.println("员工在工作");
}
public void eat() {
System.out.println("吃米饭");
}
}
package oopextendsdemo3;
public class Manager extends Employee{
private double bounus;
public Manager() {
}
public Manager(String id, String name, double salary, double bounus) {
super(id, name, salary);
this.bounus = bounus;
}
public double getBounus() {
return bounus;
}
public void setBounus(double bounus) {
this.bounus = bounus;
}
@Override
public void work() {
System.out.println("经理在管理其他人");
}
}
package oopextendsdemo3;
public class Cook extends Employee{
public Cook() {
}
public Cook(String id, String name, double salary) {
super(id, name, salary);
}
@Override
public void work() {
System.out.println("厨师在烹饪");
}
}
package oopextendsdemo3;
public class Test {
public static void main(String[] args) {
Manager m = new Manager("001", "小韩", 10000, 2000);
System.out.println(m.getId()+","+m.getName()+","+m.getSalary()+","+m.getBounus());
m.work();
m.eat();
System.out.println("=====================");
Cook c = new Cook("002", "小曹", 8000);
System.out.println(c.getId()+","+c.getName()+","+c.getSalary());
c.work();
c.eat();
}
}