static - 私有的
作用:
1.修饰属性:类属性/类变量/静态变量/静态属性,直接用类名调用
应用场景:状态码(静态常量),后续会碰到
2.修饰方法:类方法/静态方法,直接用类名调
应用场景:工具类,只需要使用类里的具体功能,那就把类视作工具类,类里的方法都是静态方法, 直接用类名调用即可
3.静态代码块:初始化数据
应用场景:初始化该类的静态属性
修饰属性:静态变量/类变量
含义:该类的每个对象都共享的,用类名调用
生命周期:
创建:类加载到方法区时,扫描该类的所有属性,把静态属性加载到静态区中
销毁:项目结束时销毁
应用场景:final + static
public class Test {
public static void main(String[] args) {
MyClass m1 = new MyClass();
MyClass m2 = new MyClass();
m1.str1 = "成员属性1";
m2.str1 = "成员属性2";
System.out.println(m1.str1);
System.out.println(m2.str1);
//静态属性是该类所有对象共享的,是类属性,所以应该用类名调用
// m1.str2 = "静态属性1";
// m2.str2 = "静态属性2";
// System.out.println(m1.str2);
// System.out.println(m2.str2);
m1.str2 = "静态属性2";
System.out.println(MyClass.str2);
}
}
class MyClass{
String str1;
static String str2;
}
修饰方法:静态方法/类方法
含义:用类名调用
应用场景:工具类
public class Test {
public static void main(String[] args) {
int[] is = {
1,5,4,2,6};
int max = MyArrays.getMax(is);
System.out.println("获取数组中的最大值:" + max);
}
}
//自定义数组工具类
class MyArrays{
public static int getMax(int[] is) {
int max = is[0];
for (int i = 1; i < is.length; i++) {
if(max < is[i]){
max = is[i];
}
}
return max;
}
}
调用时机:类(.class文件)加载到方法区时调用
public class Test {
public static void main(String[] args) {
for (String name : NameContainer.names) {
System.out.println(name);
}
}
}
//姓名容器类
class NameContainer{
static String[] names = new String[10];
static{
//初始化静态属性的数据
names[0] = "吴彦祖";
names[1] = "彭于晏";
names[2] = "何翰宇";
}
}
public class Test {
public static void main(String[] args) {
//输出:静态代码块 -> 代码 -> 构造方法
MyClass m = new MyClass();
//输出:静态代码块 -> 静态等待
MyClass.method();
}
}
class MyClass{
String str1;
static String str2;
public MyClass() {
System.out.println("构造方法");
}
{
str1 = "aaa";
System.out.println("代码块 - " + str1);
}
static{
str2 = "bbb";
System.out.println("静态代码 - " + str2);
}
public static void method() {
System.out.println("静态方法");
}
}
代码块调用法则总结:
1.代码块可以初始化属性
2.静态代码块可以初始化静态属性
3.使用该类就会把类的字节码文件(.class文件)加载到方法区中,此时就会调用静态代码块
静态变量:类变量,该类的所有对象共享一份,(JDK1.7 - 存储在静态常量区中 ,JDK1.8 - 堆中)
成员变量:该变量每个对象独享一份,存储在堆内存的对象中
成员变量 与 静态变量 的区别:
1.成员变量该类的对象独享一份,静态变量该类的所有对象共享一份
2.在成员方法中:可以调用成员变量,也可以调用静态变量
子类继承父类所有属性和方法
私有化属性和方法不能直接被调用,但是可以间接调用,见 “具体使用”
使用关键字extends继承:class 子类 extends 父类{}
public class Test {
public static void main(String[] args) {
Chinese c = new Chinese();
c.setChineseId("123..."); //操作子类的属性并调用子类的方法
c.setName("吴彦祖"); //操作父类的属性并调用父类的方法
c.setAge(18); //操作父类的属性并调用父类的方法
System.out.println(c.getChineseId());//操作子类的属性并调用子类的方法
System.out.println(c.getName()); //操作父类的属性并调用父类的方法
System.out.println(c.getAge()); //操作父类的属性并调用父类的方法
c.playTaiJi();//调用子类的方法
Japanese j = new Japanese();
j.setJapaneseId("xxx...");//操作子类的属性并调用子类的方法
j.setName("水菜丽"); //操作父类的属性并调用父类的方法
j.setAge(26); //操作父类的属性并调用父类的方法
System.out.println(j.getJapaneseId());//操作子类的属性并调用子类的方法
System.out.println(j.getName()); //操作父类的属性并调用父类的方法
System.out.println(j.getAge()); //操作父类的属性并调用父类的方法
j.playVideo();//调用子类的方法
}
}
//父类
class Person{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
//子类
class Chinese extends Person{
private String chineseId;//中国人的身份证(子类独有的属性)
//子类独有的方法
public Chinese() {
}
public Chinese(String chineseId) {
this.chineseId = chineseId;
}
public String getChineseId() {
return chineseId;
}
public void setChineseId(String chineseId) {
this.chineseId = chineseId;
}
public void playTaiJi(){
System.out.println("中国人:打太极");
}
}
//子类
class Japanese extends Person{
private String japaneseId;//日本人的身份证(子类独有的属性)
//子类独有的方法
public Japanese() {
}
public Japanese(String JapaneseId) {
this.japaneseId = JapaneseId;
}
public String getJapaneseId() {
return japaneseId;
}
public void setJapaneseId(String japaneseId) {
this.japaneseId = japaneseId;
}
public void playVideo(){
System.out.println("日本人:拍电影");
}
}
多个类里有相同的属性和方法就可以抽取出,形成一个共同的父类,减少代码的冗余
public class Test {
public static void main(String[] args) {
Son son = new Son();
}
}
class Father{
public Father() {
System.out.println("父类无参构造");
}
}
class Son extends Father{
public Son() {
//super();默认调用父类的无参构造
System.out.println("子类无参构造");
}
}
继承中的构造方法总结:
创建子类对象会不会调用父类构造方法?
会
创建子类对象调用父类构造方法的目的是什么?
创建子类对象会在堆里开辟空间,调用父类构造方法的目的是在将父类属性拷贝一份存入子类对象中
创建子类对象会创建父类对象吗?
不会
创建子类对象先调用父类构造方法还是子类构造方法?
先调用子类构造方法,子类构造方法中的第一句默认super(),意思是调用父类无参构造
创建子类对象先完成父类构造方法还是子类构造方法?
先完成父类构造方法
super 父类的,与this的使用类似
作用:
super.属性:调用父类的属性
super.方法:调用父类的方法
super():根据传参类型调用父类的构造方法
public class Test {
public static void main(String[] args) {
Chinese c = new Chinese("吴彦祖",18,"123...");
c.playTaiJi();//调用子类的方法
Japanese j = new Japanese("水菜丽",26,"xxx...");
j.playVideo();//调用子类的方法
}
}
//父类
class Person{
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
//子类
class Chinese extends Person{
private String chineseId;
public Chinese() {
}
public Chinese(String name, int age, String chineseId) {
super(name, age);//调用父类的有参构造
this.chineseId = chineseId;
}
public String getChineseId() {
return chineseId;
}
public void setChineseId(String chineseId) {
this.chineseId = chineseId;
}
public void playTaiJi(){
//调用父类的方法(间接调用父类的私有化属性)
System.out.println(super.getName() + ":打太极");
}
}
//子类
class Japanese extends Person{
private String japaneseId;
public Japanese() {
}
public Japanese(String name, int age, String japaneseId) {
super(name, age);//调用父类的有参构造
this.japaneseId = japaneseId;
}
public String getJapaneseId() {
return japaneseId;
}
public void setJapaneseId(String japaneseId) {
this.japaneseId = japaneseId;
}
public void playVideo(){
//调用父类的方法(间接调用父类的私有化属性)
System.out.println(super.getName() + ":拍电影");
}
}
如果父类里的方法不满足子类需求时,就可以重写
1.在继承关系中的子类里重写
2.返回值、方法名、参数类型必须和父类一致
3.访问修饰符不能比父类更严格
public class Test {
public static void main(String[] args) {
Student stu1 = new Student("吴彦祖", "班级号6666", "学号001");
Student stu2 = new Student("吴彦祖", "班级号6666", "学号002");
//调用重写后的equals来比较两个对象是否一致
System.out.println(stu1.equals(stu2));//false(学号不一样)
//调用重写后的toString输出想要的对象信息
System.out.println(stu1);//吴彦祖 -- 班级号6666 -- 学号001
System.out.println(stu2);//吴彦祖 -- 班级号6666 -- 学号002
}
}
class Student{
private String name;
private String classId;//班级号
private String id;//学号
public Student() {
}
public Student(String name, String classId, String id) {
this.name = name;
this.classId = classId;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//重写父类的equals方法,好处:重写以后比较两个Student对象就是比较的是两个对象的班级号和学号
@Override
public boolean equals(Object obj) {
Student stu = (Student) obj;//下转型
if(this.classId.equals(stu.classId)
&& this.id.equals(stu.id)){
return true;
}
return false;
}
//重写父类的toString方法,好处:输出Student对象,就可以获取该对象的属性信息
@Override
public String toString() {
return name + " -- " + classId + " -- " + id;
}
}
访问修饰符:决定了属性和方法的权限
做实验证明访问权限
关键字 | 访问权限 |
---|---|
private | 本类 |
默认(什么都不写) | 本类、相同包下 |
protected | 本类、相同包下、子类同包 |
public | 全局 |