static
可以使用static 修饰成员变量 | 方法|代码块。
static修饰成员变量
静态成员变量存在方法区中 并且只有一份 静态成员变量是被所有对象所共享的 静态成员变量属于类 所以在使用的时候不需要创建对象的直接使用 【类名.静态成员变量】名即可 静态成员变量 在类加载后就可以完成初始化
public class Student {
public String name;
public static int age; //静态成员
public static void main(String[] args) {
//Student.age 可直接访问 无需实例化
Student stu = new Student();
Student stu2 = new Student();
stu.name="zs";
stu2.name="ls";
stu.age = 12;
stu2.age = 18;
System.out.println(stu.name); //zs
System.out.println(stu2.name); //ls
System.out.println(stu.age); //18
System.out.println(stu2.age); //18
}
}
静态成员在内存中
由于静态成员在类加载中完成初始化且只初始化一次,因此可以直接类名.静态变量
调用无需实例化对象 再者被类的所有对象共享 所以当一个对象访问后所有对象都受到影响
static变量和非static变量的区别:
-
份数不同:静态变量:1份;非静态变量:1个对象一份
-
存储位置不同:静态变量:方法区;非静态变量:堆中
-
内存分配空间的时间不同:静态变量:第一次加载类的时候;非静态变量:创建对象的时候
-
生命周期不同。静态变量和类的生命周期相同;非静态变量的生命周期和所属对象相同
-
调用方式不同
静态变量: 通过类名调用 Student.classRoom
也可以通过对象名调用stu1.classRoom ="301" 不推荐
非静态变量:通过对象名调用 stu1.name ="小张";
static修饰成员方法
静态方法直接使用
类名.方法名()
不需要创建对象静态方法中不可以直接使用非静态内容
(非静态变量/非静态方法) 静态方法中不可以写this关键字 非静态方法是可以直接使用静态内容(静态方法/静态变量)
public class Person {
/*
* static修饰的方法叫做静态成员方法
* 静态成员方法中只能直接使用静态成员变量
* 静态成员方法推荐使用类名.方法名方式调用
* 静态成员方法中不能使用this关键
* 静态成员方法只能直接调用其他静态成员方法
*
* */
// 姓 名属性
public static String firstName;
public String lastName;
// 显示姓名的方法
public void showName(){
System.out.println(firstName+this.lastName);
methodA();
methodB();
}
public static void viewName(){
System.out.println(firstName/*+lastName*/);
methodA();
//methodB();
}
public static void methodA(){}
public void methodB(){}
public Person(String lastName) {
this.lastName = lastName;
}
public Person(){}
}
static修饰代码块
普通代码块:(执行多次) [1]在构造方法之前执行 并且每创建一次对象 就会执行一次普通代码块中内容 [2]作用:给参数进行初始化赋值的操作 (使用情况非常少) 静态代码块:(执行一次) [1]在类加载的时候执行 只会执行一次 [2] A、给静态成员变量进行初始化赋值的操作 B、初始化解析加载一些配置文件(例如我们以后学习的xml)
执行顺序 静态代码块 > 普通代码块 >构造器
public class Teacher {
private int age = 19;
private String name="张三";
//顺序 静态代码块>普通代码块>构造
//每次实例化执行 可看作匿名函数
{
System.out.println("普通代码块");
}
static {
//类加载时候执行 只执行一次 给静态变量赋值或加载配置文件
System.out.println("静态代码块");
}
public void aa(){
int age=12;
System.out.println(this.age);
}
//静态调用 类名.方法名/变量名 不可在非静态方法中调用
//静态方法中不可使用this关键字
public static void bb()
{
// aa(); //错误
}
}
总结:
优点 在调用方法的时候比较的方便 使用时候比较简单 不需要创建对象 缺点:静态内容的产生比较占用内存 由于数据的共享 会导致数据的混淆 从而导致线程不安全
封装
作用:可以更好的保护变量 使代码变得更加安全 实现: 成员变量私有化 提供公共的get/set方法 供用户使用即可
public class Base {
private String color;
private String name;
private double price;
public Base() {
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
继承
作用:实现代码的复用
父类也称作超类、基类。子类:派生类等。
Java中只有单继承,没有像C++那样的多继承。多继承会引起混乱,使得继承链过于复杂,系统难于维护。
子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
如果定义一个类时,没有调用extends,则它的父类是:java.lang.Object。
//父类
public class Base {
private String color;
private String name;
private double price;
public Base() {
}
public Base(String color, String name, double price) {
this.color = color;
this.name = name;
this.price = price;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
//子类
public class Phone extends Base{
private String size;
public Phone() {
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
}
Phone phone = new Phone();
//子类中没有这两个方法 继承自父类
phone.setName("aa");
phone.getName();
继承中的构造函数
执行顺序
A、每一个构造器第一行 JVM会默认增加super(); 默认执行父类无参构造 B、如果用户显示的提供了构造函数调用(this()/super()) 这个时候系统不在提供默认super(); C、super() 在书写的时候必须放到指定构造函数有效代码第一行 D、super()和this()不可以同时使用 注意:不是代表super关键字和this关键字不可以同时使用 E、构造函数 是不可以被继承!!!
public class Test1 {
public static void main(String[] args) {
S s =new S();
}
}
class F{
/*public F(){
System.out.println("父类中无参的构造方法");
}*/
public F(int i){
System.out.println("父类中有参数的构造方法");
}
static {
System.out.println("父类中的静态代码块");
}
{
System.out.println("父类中的普通代码块");
}
}
class S extends F{
/*
* 构造方法不能被子类继承
* 子类的构造方法一定会调用父类的构造方法
* 在子类的构造方法中,使用super()的形式默认调用父类无参构造方法
* 当父类中没有无参构造方法时,子类构造方法中必须显示书写super()并传入实参
* super()必须是子类构造放的第一行
* 当父类中没有无参构造方法, 那么子类的构造方法中 要么就只能调用父类构造方法,要么就只能调用其他构造方法
* */
public S (){
// 调用父类有参数构造方法 父类有无参构造 且子类构造中不写super() jvm默认添加
super(10);
System.out.println("子类中无参构造方法");
}
public S(int i){
this();
}
static {
System.out.println("子类中的静态代码块");
}
{
System.out.println("子类中的普通代码块");
}
}
//父类中的静态代码块
//子类中的静态代码块
//父类中的普通代码块
//父类中有参数的构造方法
//子类中的普通代码块
//子类中无参构造方法
//执行顺序 父类静态代码块--->子类中静态代码块--->父类中代码块--->父类的构造--->子类的代码块--->子类的构造
方法重写
方法重写的意义: 父类的方法没有办法满足子类的要求 这个时候我们需要进行方法重写
方法重写规则:
子类方法名与父类名称完全相同
子类方法参数列表必须与父类参数列表完全相同
子类方法返回值必须和父类方法返回值相同或【是父类方法返回值的子类】
子类方法访问权限修饰符必须和父类方法访问权限修饰符相同或比父类访问权限修饰符范围更大。 注意事项: 1.如果方法在子类中访问不到,这种情况下就不谈重写 2.静态方法不存在重写
3.使用@Override注解验证是否重写
class F{
public int a=1;
public int b=1;
public void aa()
{
System.out.println("父类方法aa");
}
public void bb(int a)
{
System.out.println("父类方法有参bb");
}
public static void cc()
{
System.out.println("父类静态方法cc");
}
public void ee()
{
System.out.println("父类方法ee");
}
}
class S extends F {
@Override
public void aa() {
System.out.println("子类方法aa");
;
}
// @Override //Override注解报错 非重写
// public void bb() {
// System.out.println("子类方法有参bb");;
// }
// @Override//Override注解报错 静态无法重写
// public static void cc() {
// System.out.println("子类方法静态cc");;
// }
public void dd() {
ee();
this.ee();
super.ee();//子类无重写 可用上述方法调用父类 变量同样适用
this.aa(); //子类有重写 this调用子类
super.aa(); //子类有重写 super调用父类
}
}
public static void main(String[] args) {
S s =new S();
s.aa();
s.bb(5);
s.ee();
s.dd();
}
//子类方法aa
//父类方法有参bb
//父类方法ee
//父类方法ee
//父类方法ee
//父类方法ee
//子类方法aa
//父类方法aa
权限修饰符
final修饰符
修饰变量: final 修饰的变量 就是一个常量
修饰方法:final修饰的方法不可以被子类重写,但是可以被重载 修饰方法:(普通方法+静态方法)
修饰类: final 修饰的类代表的是最终类 不可以被继承
注意:
final不能修饰构造方法
final修饰基本数据类型,值只能赋值一次,后续不能再赋值
final修饰引用数据类型,final Dog dog = new Dog("亚亚");,不能变化的引用变量的值,可以变化的是对象的属性