1.静态变量的特点
??使用 static 修饰变量称为静态变量,静态变量在类加载的时候初始化,并且存储在方法区。
??静态变量,是与类相关的,访问时采用“类名.”方式访问,它不同于实例变量需要 new 对象,静态变量是不需要 new 对象,不需要对象参与即可访问,没有空指针异常的发生。
//定义一个测试类
public class Student {
private String name;
private String age;
//因为每个学生都属于同一个学校,因此我们将该属性定义为静态变量
//这样就不用每创建一个对象就在堆内存为该属性开辟一个内存空间了
public static String school = "中山大学";
}
public class test {
public static void main(String[] args) {
//直接采用“类名.”方式调用
System.out.println(Student.school);
}
}
??使用 static 修饰方法称为静态方法,静态方法是不需要new对象,直接采用“类名.”调用,注意的是,因为静态方法是不需要对象的,所以里面不能访问实例对象。
//定义一个测试类
public class Student {
private String name;
private String age;
public static String school = "中山大学";
public static void test(){
System.out.println("我是静态方法")
}
}
public class test {
public static void main(String[] args) {
//直接采用“类名.”方式调用
System.out.println(Student.test());
}
}
语法
static{
??java语句;
}
执行时机
类加载时执行,并且在main方法执行之前执行,只执行一次;
//定义一个测试类
public class Student {
private String name;
private String age;
public void test(){
this.name = "路明非";
this.age = "25";
}
}
public class test {
public static void main(String[] args) {
//创建Student对象并且调用 test 方法
Student s1 = new Student();
s1.test();
/*上面可以看出,我们创建了 s1 对象,并且调用了该对象的test()方法,因为是s1调用的
所以方法中的this指的是s1对象
*/
}
}
//定义一个测试类
public class Student {
private String name;
private String age;
student(String name,String age){
//此时this.就不可以省略了,因为在构造函数中,name 和 age 是函数传进来的值
//并不等于当前对象的值,如果不加 this. 就会造成歧义
this.name = name;
this.age = age;
}
public void test(){
//this是可以省略的,因为都处于当前对象中,this.name 就等于 name
name = "路明非";
age = "25";
}
}
??通过当前的构造方法去调用本类的另一个构造方法,可以使用以下语法格式:
this(实际参数列表);
get和set方法的书写规范,set方法和get方法要尽量满足以下格式:
1.get方法的要求:
public 返回值类型 get+属性名首字母大写(无参){
??return xxx;
}
2.set方法的要求:
public void set+属性名首字母大写(有1个参数){
??xxx = 参数;
}
// 定义一个学生类
package com.xzm.test;
public class Student {
//定义类的属性,并将其私有
private int age; //年龄
private String name; //学生姓名
public Student() {}//定义无参构造方法
public Student(String stuName,int stuAge) {//定义有参构造方法,可以给属性赋值;
age = stuAge;
name = stuName;
}
//为私有属性提供访问接口set 和 get 方法
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class test {
public static void main(String[] args) {
Student student = new Student("路明非",24);
/*
* 尝试直接访问student的私有属性,编译不通过报错
* System.out.println("尝试直接访问student的私有属性:"+ student.name);
* */
/*
* 程序运行成功,输出
* 尝试使用student提供的入口的访问私有属性:路明非
* */
System.out.println("尝试使用student提供的入口的访问私有属性:"+ student.getName());
}
}
// 定义一个学生类
public class Student {
//定义类的属性,也就是学生的共同具有的属性
private int age; //年龄
private String name; //学生姓名
//定义类方法,也就是描述学生所具有的共同行为
public void eat() {
System.out.println("学生吃饭");
}
}
// 定义一个 Animal 作为父类
public class Animal {
public void eat() {
System.out.println("动物会吃饭");
}
}
// 定义一个 Cat 继承 Animal
public class Cat extends Animal {
//此时 Cat 类已经继承了 Animal 类中的方法了
}
public class test {
public static void main(String[] args){
Cat cat = new Cat();
cat.eat();
}
//此时 cat 可以直接调用 eat()方法,这样就提高了代码的复用率,以后要是其他动物类也用这个功能,直接继承该类就可以了。
}
??当父类中的方法无法满足子类的业务需求,子类就需要对继承过来的方法进行重写,进行方法的重写需要满足一下的条件:
// 定义一个 Animal 作为父类
public class Animal {
public void eat() {
System.out.println("动物会吃饭");
}
}
// 定义一个 Cat 继承 Animal
public class Cat extends Animal {
//在子类中对方法进行重写
public void eat() {
System.out.println("猫喜欢吃猫粮");
}
}
public class test {
public static void main(String[] args){
Cat cat = new Cat();
cat.eat();
}
//此时 cat 可以直接调用 eat()方法,这样就提高了代码的复用率,以后要是其他动物类也用这个功能,直接继承该类就可以了。
}
??进行方法重写时需要注意的事项:
??多态是指父类型的引用指向子类型的对象例如:
????class Animal{}
????class Cat extends
Animal{}
????Animal a = new Cat();
??以上这种赋值方式又称为向上转型(自动类型转换),需要注意的时,使用这用赋值方式调用的方法必须是父类所有的方法,不然会报错,但是最后运行的结果是由子类决定的,主要看子类是否有对该方法进行重写。
// 定义一个 Animal 作为父类
public class Animal {
public void eat() {
System.out.println("动物会吃饭");
}
}
// 定义一个 Cat 继承 Animal
public class Cat extends Animal {
//在子类中对方法进行重写
public void eat() {
System.out.println("猫喜欢吃猫粮");
}
//子类特有的方法
public void sleep() {
System.out.println("猫喜欢睡觉");
}
}
public class test {
public static void main(String[] args){
Animal a = new Cat();
//编译时先查看父类是否有该方法,有的话遍历通过,最后执行的是子类中的 eat() 方法,最后输出:猫喜欢吃猫粮
//由于在编译的时候没有在父类找到该方法,因此会报错
a.eat();
}
//此时 cat 可以直接调用 eat()方法,这样就提高了代码的复用率,以后要是其他动物类也用这个功能,直接继承该类就可以了。
}
?? 通过上面的了解,我们可以得出,向上转型时调用的方法需要是子类和父类同时拥有的,不然就编译不通过,最后执行的是子类中的方法,那么如果我们需要执行子类中特有的方法,我们需要如何做呢,这就涉及的类之间的另一种转型方式了,那就是向下转型:
?? 向下转型,又被称为强制类型转换, 通过该方式将 a 进行强转为子类 Cat ,这样就可以调用子类中特有的方法了 Cat c = (Cat)a ;
public class test {
public static void main(String[] args){
Animal a = new Cat();
//编译时先查看父类是否有该方法,有的话遍历通过,最后执行的是子类中的 eat() 方法,最后输出:猫喜欢吃猫粮
//由于在编译的时候没有在父类找到该方法,因此会报错
a.eat();
//进行向下转型,不报错
if(a instanceof Cat){
Cat c = (Cat) a;
c.eat();
}
}
// 定义一个宠物类
public class Pet {
}
// 定义猫继承宠物类
public class Cat extends Pet {
}
// 定义狗继承宠物类
public class Dog extends Pet {
}
// 测试
public class test {
public static void main(String[] args) {
//加入我们有个方法,需要根据传入不同类型的宠物,而调用不同方法,那我们就需要创建很多重载方法
//这样显然是不行的,会导致扩展力很差
Dog d = new Dog();
Cat c = new Cat();
public void feed(Dog d){}
public void feed(Cat c){}
......
//那么我们可以采用多态来解决
Dog d = Pet pet();
Cat c = Pet pet();
public void feed(Pet pet){}
}
??在父和子中有同名的属性,或者说有相同的方法,如果此时想在子类中访问父中的数据,必须使用“super.”加以区分;
??只能出先在构造方法的第一行,通过当前构造方法去调用“父类”中的构造方法,目的是创建子类对象时,先初始化父类型特征,并不是创建新对象。实际上对象只创建了1个
相关链接:
链接: 009-了解面向对象.
链接: 008-Java中方法的使用(进阶篇).
链接: 007-Java中方法的使用(基础篇).
原文:https://www.cnblogs.com/yunlixzm/p/jichu10.html