栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

类和对象(补充)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

类和对象(补充)

类和对象(补充)
    • 定义
    • 导入包中的类
      • 静态导入
    • 包的访问权限
      • protected 关键字
  • 代码块
    • 定义
  • 内部类
    • 静态内部类
    • 匿名内部类
  • 类和对象的内存布局
    • 局部变量和方法栈帧
    • 类和类变量
    • 对象和成员变量

包 定义

包 (package) 是组织类的一种方式.
使用包的主要目的是保证类的唯一性.
概念图:

导入包中的类

Java 中已经提供了很多现成的类供我们使用
举例:

import java.util.Date;
public class Test {
    public static void main(String[] args) {
        Date date = new Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
   }
}

有一个万能的导包方式,一般都可以使用import java.util.*;

import java.util.*;
public class Test {
    public static void main(String[] args) {
        Date date = new Date();
        // 得到一个毫秒级别的时间戳
        System.out.println(date.getTime());
   }
}

但是有的时候会出现冲突,情况不多,这种是=时候要用完整的类名。
举例:

import java.util.*;
import java.sql.*;
public class Test {
    public static void main(String[] args) {
        // util 和 sql 中都存在一个 Date 这样的类, 此时就会出现歧义, 编译出错
        Date date = new Date();
        System.out.println(date.getTime());
   }
}
// 编译出错
Error:(5, 9) java: 对Date的引用不明确
  java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配


常见系统包
1.java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
2. java.lang.reflect:java 反射编程包;
3. java.net:进行网络编程开发包。
4. java.sql:进行数据库开发的支持包。
5. java.util:是java提供的工具程序包。(集合类等) 非常重要
6. java.io:I/O编程开发包。

静态导入

使用 import static 可以导入包中的静态的方法和字段。
举例:

import static java.lang.System.*;
public class Test {
    public static void main(String[] args) {
        out.println("hello");
   }
}

使用这种方式可以更方便的写一些代码, 例如:

import static java.lang.Math.*;
public class Test {
    public static void main(String[] args) {
        double x = 30;
        double y = 40;
        // 静态导入的方式写起来更方便一些. 
        // double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
        double result = sqrt(pow(x, 2) + pow(y, 2));
        System.out.println(result);
   }
}
包的访问权限

我们已经了解了类中的 public 和 private. private 中的成员只能被类的内部使用.
如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部其他类使用, 但是不能在包外部的类使用.
举个例子:
Demo1和Demo2在一个包中,Test在另一个包中。

package com.bit.demo;
public class Demo1 {
    int value = 0; }
package com.bit.demo;
public class Demo2 {
    public static void Main(String[] args) {
   Demo1 demo = new Demo1();
        System.out.println(demo.value);
   }
}
// 执行结果, 能够访问到 value 变量
10
import com.bit.demo.Demo1;
public class Test {
    public static void main(String[] args) {
        Demo1 demo = new Demo1();
        System.out.println(demo.value);
   }
}
// 编译出错
Error:(6, 32) java: value在com.bit.demo.Demo1中不是公共的; 无法从外部程序包中对其进行访
问

protected 关键字

如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 “封装” 的初衷.两全其美的办法就是 protected 关键字。
对于类的调用者来说, protected 修饰的字段和方法是不能访问的
对于类的 子类 和 同一个包的其他类 来说, protected 修饰的字段和方法是可以访问的
举例:

// Animal.java
public class Animal {
    protected String name;
    public Animal(String name) {
        this.name = name;
   }
    public void eat(String food) {
        System.out.println(this.name + "正在吃" + food);
   }
}
// Bird.java
public class Bird extends Animal {
    public Bird(String name) {
        super(name);
   }
    public void fly() {
        // 对于父类的 protected 字段, 子类可以正确访问
        System.out.println(this.name + "正在飞 ︿( ̄︶ ̄)︿");
   }
}
// Test.java 和 Animal.java 不在同一个 包 之中了. 
public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal("小动物");
        System.out.println(animal.name); // 此时编译出错, 无法访问 name
   }
}

小结:
Java 中对于字段和方法共有四种访问权限
private: 类内部能访问, 类外部不能访问
默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
public : 类内部和类的调用者都能访问

代码块 定义

使用 {} 定义的一段代码.
根据代码块定义的位置以及关键字,又可分为以下四种:
普通代码块
构造块
静态块
同步代码块

普通代码块:定义在方法中的代码块

public class Main{
 public static void main(String[] args) {
 { //直接使用{}定义,普通方法块
 int x = 10 ;
 System.out.println("x1 = " +x);
 }
 int x = 100 ;
 System.out.println("x2 = " +x);
 }
}
// 执行结果
x1 = 10
x2 = 100

构造块:定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量。

class Person{ 
 private String name;//实例成员变量
 private  int age;
 private String sex;     
 public Person() {
 System.out.println("I am Person init()!");
 }   
 //实例代码块
 {
 this.name = "bit";
 this.age = 12;
 this.sex = "man";
        System.out.println("I am instance init()!");
 } 
 public void show(){
 System.out.println("name: "+name+" age: "+age+" sex: "+sex);
 } 
}
public class Main {
 public static void main(String[] args) {
 Person p1 = new Person();
 p1.show();
 }
 }
// 运行结果
I am instance init()! I am Person init()!
name: bit age: 12 sex: man

注意:实例代码块优先于构造函数执行
静态代码块:使用static定义的代码块。一般用于初始化静态成员属性

class Person{
 private String name;//实例成员变量
 private  int age;
 private String sex;
 private static int count = 0;//静态成员变量   由类共享数据 方法区
 
 public Person(){
 System.out.println("I am Person init()!");
 }
     //实例代码块
 {
 this.name = "bit";
 this.age = 12;
 this.sex = "man";
        System.out.println("I am instance init()!");
 }
 //静态代码块
 static {
 count = 10;//只能访问静态数据成员
        System.out.println("I am static init()!");
 }
 public void show(){
 System.out.println("name: "+name+" age: "+age+" sex: "+sex);
 }
}
public class Main {
 public static void main(String[] args) {
         Person p1 = new Person();
         Person p2 = new Person();//静态代码块是否还会被执行?
 }
}

注意:
静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。
静态代码块执行完毕后, 实例代码块(构造块)执行,再然后是构造函数执行

内部类

在 Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类。广泛意义上的内部类一般来说包括这四种:静态内部类、匿名内部类、成员内部类和局部内部类。
定义在class 类名{}花括号外部的,即使是在一个文件里,也不是内部类了。
比如这样:

public class A{
    
}
class B{
    
}
静态内部类
public class Test {
    
    static class B{
   }
}

和静态变量、静态方法类似,静态内部类也是和当前类(Test)绑定。使用时,也是通过Test类来调用,如:

public class Test {
    
    static class B{
   }
    public static void main(String[] args) {
        B b1 = new Test.B();
        //在当前类Test中使用时,和静态变量,静态方法类似,也可以把Test.B()省略写为B()
        B b2 = new B();
   }
}
匿名内部类

匿名内部类的定义,是在一个方法或是代码块中定义的类,并且没有显示申明类的名称,比如这样:

public class Test {    
    public static void main(String[] args) {
        //定义了一个匿名内部类
        A a = new A(){
       };
   }
}
class A{ 
}

匿名内部类是使用的非常多的一种内部类,和A a = new A(); 这样的实例操作不同,后边还有一个大括
号,表示可以重写方法,其实是定义了另外一个类(没有显示的类名,所以叫匿名)。经常用在需要实例化某个对象,但需要重写方法时,比如new接口,抽象类就是使用匿名内部类较多的方式。

public class Test {
    public static void main(String[] args) {
        //定义了一个匿名内部类
        X x = new X(){
            @Override
            public void callback() {
           }
       };
   }
}
interface X{
    void callback();
}
类和对象的内存布局 局部变量和方法栈帧
public class Main{
    public static void swap(int a, int b){
        int tmp = a;
        a = b;
        b = tmp;
        System.out.printf("swap a=%d, b=%d%n", a, b);
   }
    public static void main(String[] args) {
        int a = 1;
        int b = 2;
        swap(a, b);
        System.out.printf("main a=%d, b=%d%n", a, b);
   }
}
//输出结果为
//swap a=2, b=1 main a=1, b=2

内存布局:对应程序的执行

整体看,某个方法进入时就有自己的方法栈帧,传入参数都是局部变量,方法退出后,所有栈帧内保存的局部变量就销毁了。

类和类变量
public class Main{
    private static int COUNT;
    public static void add(){
        COUNT++;
   }
    public static void main(String[] args) {
        add();
        System.out.println(A.COUNT);
   }
}
class A{
    static int COUNT; }


对于类和类变量来说,一定要加载到类以后才会加载到方法区,并会进行初始化赋值。比如这里没有执行到A.COUNT时,A类不会加载到方法区。

对象和成员变量
public class Main{
    
    public static void main(String[] args) {
        Person p = new Person();
        p.name = "张三";
        p.age = 18;
        p.sex = "男";
   }
}
class Person{
    String name;
    int age;
    String sex = "女"; }


对象要在成员变量初始化赋值完成,构造方法调用执行初始化操作以后,才算创建完成。
对象存储在堆里边,成员变量存储在堆里边的对象中。如果是成员变量是引用类型,会指向引用的对
象。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/318699.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号