java -- static, 内部类, 权限, 参数传递

打印 上一主题 下一主题

主题 991|帖子 991|积分 2973

static关键字

static是静态修饰符,一般修饰成员。被static修饰的成员属于类,不属于单个这个类的某个对象。static修饰的成员被多个对象共享。static修饰的成员属于类,但是会影响每一个对象。被static修饰的成员又叫类成员,不叫对象的成员。
static特点

被static修饰的成员变量属于类,不属于这个类的某个对象
  1. class Demo {
  2.         public static int num = 100;
  3. }
  4. class Test {
  5.         public static void main(String[] args) {
  6.                 Demo d1 = new Demo();
  7.                 Demo d2 = new Demo();
  8.                 d1.num = 200;
  9.                 System.out.println(d1.num); //结果为200
  10.                 System.out.println(d2.num); //结果为200
  11.               }
  12. }
复制代码
静态内容是优先于对象存在,只能访问静态,不能使用this/super。静态修饰的内容存于静态区。
  1. class Demo {
  2.         //成员变量
  3.         public int num = 100;
  4.         //静态方法
  5.         public static void method(){
  6.                 //this.num; 不能使用this/super。
  7.                 //System.out.println(this.num);//报错
  8.         }
  9. }
复制代码
同一个类中,静态成员只能访问静态成员
  1. class Demo {
  2.         //成员变量
  3.         public int num = 100;
  4.         //静态成员变量
  5.         public static int count = 200;
  6.         //静态方法
  7.         public static void method(){
  8.                 //System.out.println(num); 静态方法中,只能访问静态成员变量或静态成员方法
  9.                 System.out.println(count);
  10.         }
  11. }
复制代码
static使用格式

被static修饰的成员可以并且建议通过类名直接访问。
  1. 类名.静态成员变量名
  2. 类名.静态成员方法名(参数)
  3. 对象名.静态成员变量名 // 不建议使用
  4. 对象名.静态成员方法名(参数) // 不建议使用
复制代码
  1. class Demo {
  2.         //静态成员变量
  3.         public static int num = 100;
  4.         //静态方法
  5.         public static void method(){
  6.                 System.out.println("静态方法");
  7.         }
  8. }
  9. class Test {
  10.         public static void main(String[] args) {
  11.                 System.out.println(Demo.num);
  12.                 Demo.method();
  13.         }
  14. }
复制代码
静态代码块

静态代码块:定义在成员位置,使用static修饰的代码块{ }。

  • 位置:类中方法外。
  • 执行:随着类的加载而执行且执行一次,优先构造方法的执行。
  1. public class Person {
  2.         private String name;
  3.         private int age;
  4. //静态代码块
  5.         static{
  6.                 System.out.println("静态代码块执行了");
  7.         }
  8. }
复制代码
定义静态常量

开发中,我们想在类中定义一个静态常量,通常使用public static final修饰的变量来完成定义。此时变量名用全部大写,多个单词使用下划线连接。
  1. 定义格式:
  2. public static final 数据类型 变量名 = 值;
复制代码
  1. class Company {
  2.      //比如公司名称公司地址 可能会很长很长 我们记不住 每次使用还容易打错
  3.     //这时将其定义为静态常量 方便访问 还不容易出错
  4.         public static final String COMPANY_NAME = "我的公司";
  5. }
复制代码
当我们想使用类的静态成员时,不需要创建对象,直接使用类名来访问即可。
  1. System.out.println(Company.COMPANY_NAME);
复制代码
注意:接口中的每个成员变量都默认使用public static final修饰。
所有接口中的成员变量已是静态常量,由于接口没有构造方法,所以必须显示赋值。可以直接用接口名访问。
  1. interface Inter {
  2.         public static final int COUNT = 100;
  3. }
复制代码
访问接口中的静态变量
  1. Inter.COUNT
复制代码
静态导入(了解)

静态导入就是java包的静态导入,使用import static 静态导入包 , 这样可以直接使用方法名去调用静态的方法。
静态导入格式:
  1. import static 包名.类名.方法名;
  2. import static 包名.类名.*;
复制代码
定义A类 如下, 含有两个静态方法 :
  1. public class A {
  2.     public static void print(Object s){
  3.         System.out.println(s);
  4.     }
  5.     public static void print2(Object s){
  6.         System.out.println(s);
  7.     }
  8. }
复制代码
静态导入一个类的某个静态方法 ,  使用static和类名A .方法名 , 表示导入A类中的指定方法 , 代码演示 :
  1. import static com.paopao.A.print;
  2. public class Demo {
  3.     public static void main(String[] args) {
  4.         print("test string");
  5.     }
  6. }
复制代码
如果有多个静态方法  , 使用static和类名A . * , 表示导入A类里的所有的静态方法, 代码演示 :
  1. import static com.paopao.A.*;
  2. public class Demo {
  3.     public static void main(String[] args) {
  4.         print("test string");
  5.         print2("test2 string");
  6.     }
  7. }
复制代码
权限修饰符

在Java中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限,

  • public:公共的。
  • protected:受保护的
  • default:默认的
  • private:私有的
不同权限的访问能力

publicprotecteddefault(空的)private同一类中√√√√同一包中(子类与无关类)√√√不同包的子类√√不同包中的无关类√可见,public具有最大权限。private则是最小权限。
编写代码时,如果没有特殊的考虑,建议这样使用权限:

  • 成员变量使用private ,隐藏细节。
  • 构造方法使用 public ,方便创建对象。
  • 成员方法使用public ,方便调用方法。
不加权限修饰符,其访问能力与default修饰符相同
内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类
成员内部类


  • 成员内部类 :定义在类中方法外的类。
定义格式:
  1. class 外部类 {
  2.     class 内部类{
  3.     }
  4. }
复制代码
在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。比如,汽车类Car 中包含发动机类Engine ,这时,Engine 就可以使用内部类来描述,定义在成员位置。
代码举例:
  1. class Car { //外部类
  2.     class Engine { //内部类
  3.     }
  4. }
复制代码
访问特点


  • 内部类可以直接访问外部类的成员,包括私有成员。
  • 外部类要访问内部类的成员,必须要建立内部类的对象。
创建内部公共(public)类对象格式:
  1. 外部类名.内部类名 对象名 = new 外部类型().new 内部类型();
复制代码
访问演示,代码如下:
定义类:
  1. public class Person {
  2.     private  boolean live = true;
  3.     class Heart {
  4.         public void jump() {
  5.             // 直接访问外部类成员
  6.             if (live) {
  7.                 System.out.println("心脏在跳动");
  8.             } else {
  9.                 System.out.println("心脏不跳了");
  10.             }
  11.         }
  12.     }
  13.     public boolean isLive() {
  14.         return live;
  15.     }
  16.     public void setLive(boolean live) {
  17.         this.live = live;
  18.     }
  19. }
复制代码
定义测试类:
  1. public class InnerDemo {
  2.     public static void main(String[] args) {
  3.         // 创建外部类对象
  4.         Person p  = new Person();
  5.         // 创建内部类对象
  6.         Person.Heart heart = p.new Heart();
  7.         // 调用内部类方法
  8.         heart.jump();
  9.         // 调用外部类方法
  10.         p.setLive(false);
  11.         // 调用内部类方法
  12.         heart.jump();
  13.     }
  14. }
  15. 输出结果:
  16. 心脏在跳动
  17. 心脏不跳了
复制代码
内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号
比如,Person$Heart.class
匿名内部类


  • 匿名内部类 :是内部类的简化写法。它的本质是一个带具体实现的 父类或者父接口的 匿名的 子类对象
开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,

  • 定义子类
  • 重写接口中的方法
  • 创建子类对象
  • 调用重写后的方法
格式
  1. new 父类名或者接口名(){
  2.     // 方法重写
  3.     @Override
  4.     public void method() {
  5.         // 执行语句
  6.     }
  7. };
复制代码
使用方式

以接口为例,匿名内部类的使用,代码如下:
定义接口:
  1. public abstract class FlyAble{
  2.     public abstract void fly();
  3. }
复制代码
匿名内部类可以通过多态的形式接受
  1. public class InnerDemo01 {
  2.     public static void main(String[] args) {
  3.         /*
  4.                 1.等号右边:定义并创建该接口的子类对象
  5.                 2.等号左边:是多态,接口类型引用指向子类对象
  6.        */
  7.         FlyAble  f = new FlyAble(){
  8.             public void fly() {
  9.                 System.out.println("我飞了~~~");
  10.             }
  11.         };
  12.     }
  13. }
复制代码
匿名内部类直接调用方法
  1. public class InnerDemo02 {
  2.     public static void main(String[] args) {
  3.         /*
  4.                 1.等号右边:定义并创建该接口的子类对象
  5.                 2.等号左边:是多态,接口类型引用指向子类对象
  6.        */
  7.                new FlyAble(){
  8.             public void fly() {
  9.                 System.out.println("我飞了~~~");
  10.             }
  11.         }.fly();
  12.     }
  13. }
复制代码
方法的形式参数是接口或者抽象类时,也可以将匿名内部类作为参数传递
  1. public class InnerDemo3 {
  2.     public static void main(String[] args) {
  3.         /*
  4.         1.等号右边:定义并创建该接口的子类对象
  5.         2.等号左边:是多态,接口类型引用指向子类对象
  6.        */
  7.         FlyAble  f = new FlyAble(){
  8.             public void fly() {
  9.                 System.out.println("我飞了~~~");
  10.             }
  11.         };
  12.         // 将f传递给showFly方法中
  13.         showFly(f);
  14.     }
  15.     public static void showFly(FlyAble f) {
  16.         f.fly();
  17.     }
  18. }
复制代码
以上可以简化,代码如下:
  1. public class InnerDemo2 {
  2.     public static void main(String[] args) {               
  3.         /*
  4.                创建匿名内部类,直接传递给showFly(FlyAble f)
  5.         */
  6.         showFly( new FlyAble(){
  7.             public void fly() {
  8.                 System.out.println("我飞了~~~");
  9.             }
  10.         });
  11.     }
  12.     public static void showFly(FlyAble f) {
  13.         f.fly();
  14.     }
  15. }
复制代码
引用类型的传递

类名作为方法参数和返回值


  • 类名作为方法的形参
    方法的形参是类名,其实需要的是该类的对象
    实际传递的是该对象的【地址值】
  • 类名作为方法的返回值
    方法的返回值是类名,其实返回的是该类的对象
    实际传递的,也是该对象的【地址值】
  • 示例代码:
    1. public class Person{
    2.   public void eat(){
    3.     System.out.println("人吃了");
    4.   }
    5. }
    6. public class Test{
    7.   public static void main(String[] args){
    8.         method(new Person());
    9.                    Person p = method2();
    10.   }
    11.   pubic static void method(Person p){
    12.        p.eat();
    13.   }
    14.   public static Person method2(){
    15.             return new Person();
    16.   }
    17. }
    复制代码
抽象类作为形参和返回值


  • 抽象类作为形参和返回值

    • 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
    • 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象

  • 示例代码:
    1. public abstract class Animal{
    2.           public abstract void eat();
    3. }
    4. public class Cat extends Animal{
    5.   public void eat(){
    6.     System.out.println("猫吃鱼");
    7.   }
    8. }
    9. public class Test{
    10.   public static void main(String[] args){
    11.       method(new Cat());
    12.    
    13.      Animal a = method2();
    14.    
    15.   }
    16.   public static void method(Animal a){
    17.        a.eat();
    18.   }
    19.   public static Animal method2(){
    20.             return new cat();
    21.   }
    22. }
    复制代码
接口名作为形参和返回值


  • 接口作为形参和返回值

    • 方法的形参是接口名,其实需要的是该接口的实现类对象
    • 方法的返回值是接口名,其实返回的是该接口的实现类对象

  • 示例代码:
    1. public interface Fly{
    2.     public abstract void fly();
    3. }
    4. public class Bird implements Fly{
    5.   public void fly(){
    6.     System.out.println("我飞了");
    7.   }
    8. }
    9. public class Test{
    10.   public static void main(String[] args){
    11.       method(new Bird());
    12.    
    13.      Fly f = method2();
    14.    
    15.   }
    16.   public static void method(Fly f){
    17.              f.fly();
    18.   }
    19.   public static Fly method2(){
    20.             return new Bird();
    21.   }
    22. }
    复制代码
练习
  1. 公司类
  2. ​        属性
  3. ​                总资产属性
  4. ​                所有员工属性
  5. ​        方法
  6. ​                发工资方法:从总资产中减去所有员工支出。
  7. 员工:
  8. ​        属性
  9. ​                姓名
  10. ​                工号
  11. ​                存款
  12. ​                工资
  13. 经理、厨师、服务员均为员工子类。经理在员工基础上添加奖金属性。发完工资后,请查看所有员工的存款情况.
  14. 公司类加入调整员工工资方法:返回值为void       
  15. 参数为:被调整工资的员工与调整金额(涨工资为正数、降工资为负数)。
  16. ​                方法体逻辑为,在员工工资的基础上调整相应的金额
  17. 在上边需求基础上,添加评选幸运员工(随机抽取一名员工并返回)。
复制代码
点击查看代码
  1. // Employee.java
  2. public class Employee {
  3.     String name;
  4.     String id;
  5.     private double deposit;
  6.     private double salary;
  7.     public Employee() {}
  8.     public Employee(String name, String id, double deposit, double salary) {
  9.         this.name = name;
  10.         this.id = id;
  11.         this.deposit = deposit;
  12.         this.salary = salary;
  13.     }
  14.     public double getDeposit() {
  15.         return deposit;
  16.     }
  17.     public void setDeposit(double deposit) {
  18.         this.deposit = deposit;
  19.     }
  20.     public double getSalary() {
  21.         return salary;
  22.     }
  23.     public void setSalary(double salary) {
  24.         this.salary = salary;
  25.     }
  26. }
复制代码
  1. // Manager.java
  2. public class Manager extends Employee {
  3.     private double bonus;
  4.     public Manager() {
  5.     }
  6.     public Manager(String name, String id, double deposit, double salary, double bonus) {
  7.         super(name, id, deposit, salary);
  8.         this.bonus = bonus;
  9.     }
  10.     public double getBonus() {
  11.         return bonus;
  12.     }
  13.     public void setBonus(double bouns) {
  14.         this.bonus = bouns;
  15.     }
  16. }
复制代码
  1. // Cooker.java
  2. public class Cooker extends Employee {
  3.     public Cooker() {
  4.     }
  5.     public Cooker(String name, String id, double deposit, double salary) {
  6.         super(name, id, deposit, salary);
  7.     }
  8. }
复制代码
  1. // Waiter.java
  2. public class Waiter extends Employee{
  3.     public Waiter() {
  4.     }
  5.     public Waiter(String name, String id, double deposit, double salary) {
  6.         super(name, id, deposit, salary);
  7.     }
  8. }
复制代码
  1. // Company.java
  2. import java.util.ArrayList;
  3. import java.util.Random;
  4. public class Company {
  5.     private double property;
  6.     private ArrayList<Employee> employeeArrayList;
  7.     public Company() {
  8.     }
  9.     public Company(double property, ArrayList<Employee> employeeArrayList) {
  10.         this.property = property;
  11.         this.employeeArrayList = employeeArrayList;
  12.     }
  13.     public double getProperty() {
  14.         return property;
  15.     }
  16.     public void setProperty(double property) {
  17.         this.property = property;
  18.     }
  19.     public ArrayList<Employee> getEmployeeArrayList() {
  20.         return employeeArrayList;
  21.     }
  22.     public void setEmployeeArrayList(ArrayList<Employee> employeeArrayList) {
  23.         this.employeeArrayList = employeeArrayList;
  24.     }
  25.     public Boolean existEmployee(){
  26.         if (employeeArrayList == null || employeeArrayList.size() == 0) {
  27.             return false;
  28.         }
  29.         return true;
  30.     }
  31.     public void printEmployeeInfo(Employee employee) {
  32.         System.out.println("工号: " + employee.id);
  33.         System.out.println("姓名: " + employee.name);
  34.         System.out.println("存款: " + employee.getDeposit());
  35.         System.out.println("工资: " + employee.getSalary());
  36.         if (employee instanceof Manager) {
  37.             System.out.println("奖金: " + ((Manager) employee).getBonus());
  38.         }
  39.         System.out.println("==============================");
  40.     }
  41.     public void showEmployeeInfo() {
  42.         ArrayList<Employee> employeeArrayList = getEmployeeArrayList();
  43.         if (!existEmployee()){
  44.             System.out.println("暂无员工");
  45.             return ;
  46.         }
  47.         for (int i = 0; i < employeeArrayList.size(); i++) {
  48.             Employee employee = employeeArrayList.get(i);
  49.             printEmployeeInfo(employee);
  50.         }
  51.     }
  52.     public void showEmployeeInfo(Employee employee){
  53.         printEmployeeInfo(employee);
  54.     }
  55.     public void payingSalaries() {
  56.         if (!existEmployee()){
  57.             System.out.println("暂无员工");
  58.             return ;
  59.         }
  60.         for (int i = 0; i < employeeArrayList.size(); i++) {
  61.             Employee employee = employeeArrayList.get(i);
  62.             property -= employee.getSalary();
  63.             employee.setDeposit(employee.getDeposit() + employee.getSalary());
  64.             if (employee instanceof Manager) {
  65.                 property -= ((Manager) employee).getBonus();
  66.                 employee.setDeposit(employee.getDeposit() + ((Manager) employee).getBonus());
  67.             }
  68.         }
  69.     }
  70.     public Employee randomEmployee() {
  71.         Random r = new Random();
  72.         return employeeArrayList.get(r.nextInt(employeeArrayList.size()));
  73.     }
  74.     public void chageSalary(Employee employee, double howMuch) {
  75.         employee.setSalary(employee.getSalary() + howMuch);
  76.     }
  77. }
复制代码
  1. // Demo.java
  2. import java.util.ArrayList;
  3. public class Demo {
  4.     public static void main(String[] args) {
  5.         ArrayList<Employee> employeeArrayList = new ArrayList<>();
  6.         employeeArrayList.add(new Manager("张三","001",10000,2000,3000));
  7.         employeeArrayList.add(new Cooker("李四","002",1000, 2000));
  8.         employeeArrayList.add(new Waiter("王五","003",2000,2000));
  9.         Company company = new Company(1000000, employeeArrayList);
  10.         company.showEmployeeInfo();
  11.         company.payingSalaries();
  12.         company.showEmployeeInfo();
  13.         Employee employee = company.randomEmployee();
  14.         company.showEmployeeInfo(employee);
  15.         company.chageSalary(employee, -200);
  16.         System.out.println(employee.getSalary());
  17.     }
  18. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

商道如狼道

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表