static 关键字概述
关键字可以使用的位置:类,成员变量,局部变量,成员方法,构造方法
static:表示静态的,可以修饰成员变量,成员方法。
static 所修饰的方法和变量会存储在方法区内,属于类,不再属于对象自己,只有一份。
package demo01_static关键字;
public class Student {
```
String name;
static String room = "314"; //所在教室 用static修饰的成员变量 属于类 有时也叫静态变量 不再属于对象自己 被所有对象共享
public Student(String name) {
this.name = name;
}
```
}
package demo01_static关键字;
public class Test {
```
public static void main(String[] args) {
Student one = new Student("科比");
one.room = "514教室";
System.out.println(one.name);
System.out.println(one.room);
Student two = new Student("韦德");
System.out.println(two.name);
System.out.println(two.room);
}
```
}
static关键字访问方式
1.可以创建对象,通过对象访问,并且如果是成员变量的话,可以通过调用修改。方法不能重写。
2.使用类名调用(支持)
静态属性和静态方法可以被extends方式继承,但是不可以被implements方式继承。
static关键字内存分配时机
一,在程序运行期间,在第一次创建对象时,会给该静态成员先分配内存,然后再执行构造方法。
顺序:
1.给静态成员分配内存
2.给普通成员分配内存
3.执行构造方法
注:静态成员只会被加载一次,静态成员会比对象先进入内存。
二,在程序运行期间,第一次访问该类静态成员时,jvm会给该类的所有静态成员分配内存。
第一次使用该类的时候,静态成员会和类一起被加载。
静态成员访问规则
package demo02_static关键字_静态成员访问规则;
public class Student {
int age = 18;
String name;
static String room = "314"; //所在教室 用static修饰的成员变量 属于类 有时也叫静态变量 不再属于对象自己 被所有对象共享
```
public Student(String name) {
this.name = name;
}
public static void study(){//静态方法
System.out.println("学好java,高薪就业");
```
// System.out.println(age);//编译报错 静态方法不能访问非静态成员 因为静态成员比对象先进入内存
}
```
public void show(){
System.out.println(room);//在非静态方法中可以访问静态成员
}
```
}
package demo01_static关键字;
public class Student {
```
String name;
static String room = "314"; //所在教室 用static修饰的成员变量 属于类 有时也叫静态变量 不再属于对象自己 被所有对象共享
public Student(String name) {
this.name = name;
}
public static void study(){//静态方法
System.out.println("学好java,高薪就业");
}
```
}
static关键字-静态代码块
1.定义在类种方法外,用static修饰的一组代码
2.特点:静态代码块在创建对象时,或者第一次使用该静态类静态成员时会被执行而且只执行一次,并且在构造方法之前执行。
3.作用:静态代码块就是为静态变量进行初始化的,因为有时候静态变量初始化代码不是一句就能够完成的。
package demo01_static关键字;
public class Student {
```
String name;
static String room = "314"; //所在教室 用static修饰的成员变量 属于类 有时也叫静态变量 不再属于对象自己 被所有对象共享
public Student(String name) {
this.name = name;
}
```
}
package demo01_static关键字;
public class Test {
```
public static void main(String[] args) {
Student one = new Student("科比");
one.room = "514教室";package demo03_static关键字_静态代码块;
```
public class Test {
```
public static void main(String[] args) {
```
// Student one = new Student(18);
// Student two = new Student(20);
// System.out.println(Student.room);
System.out.println(Student.arr[0]);
System.out.println(Student.arr[1]);
System.out.println(Student.arr[2]);
```
System.out.println(Student.arr[0]);//和第一次输出的一样,因为静态代码块只执行一次
}
```
}
package demo03_static关键字_静态代码块;
import java.util.Random;
public class Student {
int age;
```
static String room = "314教室";
static int[] arr = new int[10];//静态变量
static {
System.out.println("静态代码块");
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(100) + 1;
}
}
public Student(int age) {
this.age = age;
System.out.println("有参构造方法");
}
/**
* 需求:为arr每一个元素初始化一个1-100的随机数
* 1.生成一个1-100的随机数 Random
* 2.遍历arr数组 将随机数赋值给arr数组中的每一个元素
*/
```
// Random random = new Random();
// fo
// public Student(){//只能用静态代码块为静态变量初始化
// Random random = new Random();
// for (int i = 0; i < arr.length; i++) {
// arr[i] = random.nextInt(100) + 1;
// }
// }
}
```
System.out.println(one.name);
System.out.println(one.room);
Student two = new Student("韦德");
System.out.println(two.name);
System.out.println(two.room);
}
```
}
开发中static的应用
static修饰的成员属于类的,被所有对象共享的,在实际开发中如果有一些数据和方法是被大家共用的,就可以使用static修饰,可以直接使用类名进行调用
class Const{
public static final double PI= 10;//定义常量π,并且被final修饰的变量名为常量,全部字母用大写
//创建一个方法用来求最大值
public static int max (int[] arr){
int max = arr[0];
for(int i = 1 ; i <arr.length; i ++ ){
if(arr[i]>max){
max = arr[i];
}
return max;
}
}
}
class Test{
public static void main(String[] args){
System.out.println(Const.PI);//调用公共类中的常量
int[] arr = {1,2,3,4}
System.out.println(max(arr));//调用公共类中的方法
}
}
接口
1.比抽象类还要抽象的一种引用类型,方法的集合,在jdk1.7时只能定义抽象方法。jdk1.8之后接口 可以定义默认方法和静态方法。
2.定义及内容
通过interface关键字定义接口
格式:
public interface Animal{
}
使用:接口不可以创建对象,接口有一个实现类,使用implemets来实现接口,类似于继承。
实现类必须重写接口类中的全部抽象方法。
public interface Animals{
public abstract void eat();//抽象方法
public abstract void sleep();
}
public class Cat implements Animals{
//必须重写接口类里面的所有抽象类
public void eat(){
System.out.println("小猫吃鱼");
}
public void sleep(){
System.out.println("小猫睡觉");
}
}
public class Test{
public static void main(String[] args){
Cat cat = new Cat;
cat.eat();
cat.sleep();
}
}
接口类里面的方法:抽象方法,默认方法,静态方法。
public interface Animals{
//抽象方法
public abstract void eat();
//默认方法
public default void show(){}//可以被子类继承,子类可重写也可以不重写
//静态方法
public static void demo(){}//不能够被接口继承,可以通过接口名调用,但是可以extends方式继承。
public static final int AGE = 10;//静态属性(此刻AGE是常量,被final保护)
}
public class Dog implements Animals{//实现类
//必须重写抽象方法
public void eat(){};
//默认方法可以重写也可以不重写
//静态方法不可以被继承
}
public class Test{
Dog dog = new Dog();
dog.eat();//抽象类被继承重写。
dog.show();//默认类被继承,但是Dog没有重写。
dog.demo//报错,因为静态类不会被继承,不可以通过此方式调用。
Animals.demo//通过接口类名调用静态方法。
Animals.AGE//通过接口类名调用静态属性。
}
默认方法的意义:解决接口升级的问题,如果在程序已经投入使用阶段进行维护添加方法,可以使用默认方法添加,如果使用抽象方法将会引起程序报错,产生损失。
接口的作用及意义:
解决java单继承的弊端。子类可以继承一个类的同时,实现一个或者多个接口。
子类必须是先继承,后实现接口,并且实现接口数量不限制。
子类实现多接口的冲突
常量:若实现的多接口类中有相同名称常量,实现类种调用该常量会引起报错
抽象方法:若实现的多接口类有相同的名称的抽象方法,只需要重写一次。
默认方法:若实现的多接口类中有相同名称的默认方法,只需要重写一次,确认最终版本。
静态方法:若实现的多接口类中有相同名称的静态方法,不会报错,也无需重写,因为不会被子类继承
子类先继承后实现中被继承类和接口类的冲突
常量:若继承类和接口类中有相同名称的常量,子类调用时报错
抽象方法:改写一次,因为是先继承,继承时候改写继承父类中的抽象方法之后,默认为此改写的抽象方法也将接口类中的抽象方法改写完毕(如果继承父类中某一个非抽象方法和接口类中的抽象方法重名,则无需改写,因为默认先继承的为接口类中的改写完毕版本)
默认方法:不会报错,和抽象方法类似,默认为继承父类的同名方法将默认方法改写
静态方法:不会报错,接口类中的静态方法不会被继承,继承父类会继承,不会产生编译错误。
单接口继承多接口
和先继承后实现的情况相同
多态(java三种特性:继承,封装,多态)
多态的概念:同一种行为表现出不同的状态
格式
父类引用指向子类对象(左父右子)
父类 名称 = new 子类
多态的前提是继承,没有继承就没有多态
多态时访问成员的特点
总体规则是:当访问是都是访问父类的,不能访问子类特有的成员。(子类中除了子类改写了父类的方法可以被访问,其余的都不行!继承下来的属性(有参构造)可以)
当访问成员变量,访问的都是父类的,看得是引用。
当访问方法时候,访问的都是子类的,看得是对象。
class Animals{
int age = 15;
public void eat(){}
}
class Cat extends Animals{
int age 3;
public void eat(){
}
}
class Test {
Animals animals = new Cat();
System.out.println(animal.age);//调用的是父类的
animals.eat();//调用的是子类的
}
多态的几种形式
1.父类的多态
2.接口类的多态
3.父抽象类的多态
使用方法一样。
多态的几种使用方式
1.变量的多态
Animals animals = new Cat();
2.方法参数的多态,方便接口实现双向
class Test{
public static void main(String args[]){
Cat cat = new Cat();
shouEat(cat);
Animals animals = new Dog();
shouEat(animals);
//以上两种方法都可以
}
public static void shouEat(Animals animals){//实参是这个父类的任何一个子类,就可以调用此方法。
animals.eat();
//此方法的好处是,任何子类都可以使用这个方法,若形参是某个子类的对象的话,一个子类调用这个方法,就得再写一个这个方法。
}
}
3.方法返回值的多态,方便接口实现双向
public static Animals getAnimals(){//可以返回任何的Animals 子类
Cat cat = new cat();
return cat;
}
多态的好处和弊端
1.弊端:不能够访问子类的特有成员
2.好处:有利于程序扩展,主要体现在与方法参数的多态和方法返回值的多态上。
多态的转型
1.向上转型:
Animals animals = new Cat();
弊端:不能够访问子类特有成员。
2.向下转型(消除多态弊端)
class Test{
public static void main(String[] args){
Animals animal = new Cat;
//向下转型有风险,需要判断 关键字 instanof
if(animal instanceof Cat){
Cat cat = (Cat)animal;
}
Dog dog = (Dog)animal;//编译通过 java.lang.ClassCastException 类转换异常
//向下转型前,先用向上转型。
}
}
笔记本电脑案例
package com.day02.笔记本电脑案例;
public class Computer {
public void start() {
System.out.println("开机!");
}
public void off() {
System.out.println("关机!");
}
public static void computerPei(USB usb) {
usb.run();
}
}
package com.day02.笔记本电脑案例;
public class Keyboard implements USB {
public void run(){
System.out.println("敲打,化身键盘侠,刺啦~划拉~wu~");
}
}
package com.day02.笔记本电脑案例;
public class Mouse implements USB {
public void run(){
System.out.println("移动操控哔哔哔,丢丢丢~");
}
}
package com.day02.笔记本电脑案例;
public interface USB {
public abstract void run() ;
}
package com.day02.笔记本电脑案例;
public class Test {
public static void main(String[] args) {
Computer computer = new Computer();
computer.start();
USB usbmouse = new Mouse() ;//Mouse mouse = new Mouse();都可以
computer.computerPei(usbmouse);
Keyboard keyboard = new Keyboard();
computer.computerPei(keyboard);
computer.off();
}
}
内部类
1.定义在类中的类
成员内部类:正常的内部类
局部内部类:定义在成员方法中的内部类
匿名内部类:
成员内部类:
class Outer{
private int a = 100;
class Insid {
public void show(){
System.out.println(a)//内部类可以访问外部类的成员属性,包括私有的。
}
}
}
class Tets{
main{
Outer.Insid insid = new Outer().new Insid();//内部类对象的创建
insid.show();
}
}
局部内部类:
定义在方法中的内部类
class Outer{
public void show(){
final int a = 100;
class Insid{//局部内部类
sout(a)//局部内部类访问局部变量的时候,此变量必须是final 方法和类的生存周期不同的原因
}
Inside inside = new Inside();//局部内部类创建对象只能在方法中
inside.demo();
}
}
class Test{
mian{
Outer outer = new Outer();
outer.show();
}
}
匿名内部类:省去了一个变量(引用),代码辨识度太差。
class Test{
mian{
Cat cat = new Cat();
cat.eat();
Animals animal = new Cat();
animal.eat();
/*
匿名内部类
new 父类/父类接口(){
重写抽象方法
}
*/
new Animals(){
public void eat(){
sout("hjsakd");
}
}.eat();
}
}