Java中Class类的作用与深入理解

  在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。JVM利用运行时信息选择相应的方法执行。而保存这些信息的类称为Class。可能容易产生混淆,容易想到class。不过二者没什么关系,class不过是描述类的一个关键字。而Class却是保存着运行时信息的类。

它能做什么?Class类可以帮助我们在程序运行时分析类,说白了就是获取类中的值。可能瞬间就想到了反射,没错!Class一般就是和反射配套使用的,因为我们向Class提供一个类或一个类的类名,Class就可以提供我们很多信息,比如属性/方法/修饰符/构造器/类名等等。然后我们就可以进一步进行反射。不过,还是先来简单了解下Class类的内容和使用方式吧!

获取Class对象的三种方式(实例采用Person类)

方式1:通过Object类的getObject()方法   

Person p = new Person();
Class c = p.getClass();

方式2: 通过 类名.class 获取到字节码文件对象(任意数据类型都具备一个class静态属性,看上去要比第一种方式简单)。

Class c2 = Person.class

方式3: 通过Class类中的方法(将类名作为字符串传递给Class类中的静态方法forName即可)。  

Class c3 = Class.forName("Person")

注意:第三种和前两种的区别

前两种你必须明确Person类型.

后面是指定这种类型的字符串就行.这种扩展更强.我不需要知道类名.我只提供字符串,按照配置文件加载就可以了

代码演示:

public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//通过Object类的getObject()方法   
Person p = new Person();
Class c1 = p.getClass();
System.out.println(c1); //类名.class 获取到字节码文件对象
Class c2 =Person.class;
System.out.println(c2); //通过Class类中的方法forName()
Class c3 = Class.forName("cn.shiqi.demo1.Person");
System.out.println(c3);
}
}
class Person{
  
}

类成员的理解

  类成员是属于整个类的,而不是属于对象的。因此创建一个对象时,只会为实例变量分配内存,而不会为类成员变量分配内存,类成员变量是在类初始化时分配的内存(执行main()方法之前),所以当类变量初始化以后,实例变量很可能还没有分配内存,因此类成员是不能访问实例变量的。
Java中对象可以访问类成员变量(很多语言是不允许对象访问类变量的,只能访问实例变量),一般都是通过类来访问对象。

public class NullAccessStatic
{
private static void test()
{
System.out.println("static修饰的类方法");
}
public static void main(String[] args)
{
// 定义一个NullAccessStatic变量,其值为null
NullAccessStatic nas = null;
//使用null对象调用所属类的类方法
//下面代码一切正常,可以使用空对象访问类成员,进一步说明类成员是属于类的,其并不在对应实例中
nas.test();
}
}
//注意:如果一个null对象访问实例成员,将会引发NullPointException异常,
//因为null表明该实例根本不存在,既然实例不存在,它的实例成员也就不存在。

如下所示:

public class Main {
public static int str1=1;//类成员
int b=2;//实例成员
public static void main(String[] args) {
// System.out.println("Hello World!"); /*String str2 = new String("str")+new String("01");
str2.intern();//从常量池中找,如果有直接返回该引用
String str1 = "str01";
System.out.println(str2 == str1);*/ Main a=null;//表明实例根本不存在,既然实例不存在,那么他的实例变量和方法自然也不存在
// Main a=new Main();
System.out.println(a.str1);
System.out.println(a.b);//空指针异常
}
}

2 单例类
大部分时候把类的构造器访问控制权限都定义为public,允许任何类自由创建该类的对象。但在某些时候,允许其他类自由创建该类对象没有任何意义,还可能造成系统性能下降(因为频繁的创建对象,且回收对象会带来系统开销问题),这是就需要引入单例类了。如果一个类始终只能创建一个类,则这个类就被称为单例类。
要实现单例类需要做哪些处理:

将类的构造器隐藏起来,用private,但又需要创建一个对象,就需要提供一个public方法,用于创建该对象,且该方法必须使用static修饰(因为调用该方法之前还不存在对象,因此调用该方法的只能是类)
除此之外,还需要缓存已经创建好的对象,否则无法知道曾经是否创建过对象,也就无法保证只创建一个对象。为此该类需要提供一个成员变量来保存曾经创建过的对象,因为该成员变量需要被上面的方法调用,故该成员变量不许用static修饰。

class Singleton
{
////使用一个类成员变量来缓存曾经创建过的实例
private static Singleton instance;
//对构造器使用private修饰,隐藏该构造器
private Singleton(){}//只能本类访问
// 提供一个静态方法,用于返回Singleton实例
//该方法可以加入自定义控制,保证指残生一个Singleton对象
public static Singleton getInstance()
{
// 如果instance为null,则表明不曾创建Singleton对象
//如果instance不为null,则表明已经创建过Singleton对象
// 将不会创建新的实例
if (instance == null)
{
// 创建一个Singleton对象,将其缓存起来
instance = new Singleton();
}
return instance;
}
}
public class SingletonTest
{
public static void main(String[] args)
{
//创建Singleton对象不能通过构造器
//只能通过getInstance方法来得到实例
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2); //将输出true
}
}

Java中Class和单例类的作用与类成员的理解的更多相关文章

  1. java中安全的单例与不安全的单例

    java中安全的单例与不安全的单例 1.内部静态类(安全的) public class Singleton { private static class SingletonHolder{ privat ...

  2. java 中的懒汉单例和饿汉单例模式

    //-------------------------------------------------------------饿汉模式--开始----------------------------- ...

  3. Java中的懒汉式单例与饿汉式单例实例详解

    懒汉式单例:线程非安全,当被调用的时候才创建实例,效率较高 public class LazySingleton { private static LazySingleton lazySingleto ...

  4. Java学习笔记之---单例模型

    Java学习笔记之---单例模型 单例模型分为:饿汉式,懒汉式 (一)要点 1.某个类只能有一个实例 2.必须自行创建实例 3.必须自行向整个系统提供这个实例 (二)实现 1.只提供私有的构造方法 2 ...

  5. OC中两种单例实现方式

    OC中两种单例实现方式 写在前面 前两天探索了一下C++ 的单例,领悟深刻了许多.今天来看看OC中的单例又是怎么回事.查看相关资料,发现在OC中一般有两种实现单例的方式,一种方式是跟C++ 中类似的常 ...

  6. Java中设计模式之单例设计模式-1

    单例作用 1 节省内存 2 可以避免多种状态导致状态冲突 单例的创建步骤 1 私有化构造方法 2 私有化声明的属性 3 getInstance 4 方法需要静态 单例分类 1.懒汉式 2.饿汉式 两种 ...

  7. Java中创建操作文件和文件夹的工具类

    Java中创建操作文件和文件夹的工具类 FileUtils.java import java.io.BufferedInputStream; import java.io.BufferedOutput ...

  8. Java中带包(创建及引用)的类的编译

    Java中带包(创建及引用)的类的编译与调试 java源程序的编译大家都知道,也就是cmd中到源文件所在目录下javac **.java即可,当程序中有包声明还能简简单单的直接javac **.jav ...

  9. JAVA的设计模式之单例设计模式

    1.确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例. 1)理论 Java Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在. 使用Singl ...

随机推荐

  1. PyCharm设置完自动上传,却不会自动上传任何内容

    Upload changed files automatically to the default server 选择了 Always 下面有一个提示 Default server or group ...

  2. Linux:系统的启动过程

    Linux系统的启动过程 过程 通电-> BIOS-> LILO/GRUB-> Kernel Boot-> init->rc.sysinit init->rc -& ...

  3. 005 C/C++ 数据类型_void

    1.void的字面意思是'无类型'.void * 是无类型指针,void * 可以指向任何类型的数据. 2.数据类型的分装: int InitHardEnv(void ** handle); 典型的内 ...

  4. TensorFlow从1到2(十二)生成对抗网络GAN和图片自动生成

    生成对抗网络的概念 上一篇中介绍的VAE自动编码器具备了一定程度的创造特征,能够"无中生有"的由一组随机数向量生成手写字符的图片. 这个"创造能力"我们在模型中 ...

  5. python的imread、newaxis

    一:imread 用来读取图片,返回一个numpy.ndarray类型的多维数组,具有两个参数: 参数1 filename, 读取的图片文件名,可以使用相对路径或者绝对路径,但必须带完整的文件扩展名( ...

  6. acwing 17. 从尾到头打印链表

    题目地址 https://www.acwing.com/problem/content/description/18/ 来源:剑指Offer 输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值. ...

  7. What is Market Intelligence and how is it Used?

    https://blog.globalwebindex.com/marketing/market-intelligence/ Market intelligence is the gathering ...

  8. Linux下修改Mysql密码的三种方式

    前言 有时我们会忘记Mysql的密码,或者想改一个密码,以下将对这两种情况修改密码的三种解决方法做个总结 本文都以用户为 root 为例 一.拥有原来的myql的root的密码 方法一: 在mysql ...

  9. C语言--计算程序执行时间

    C语言–计算程序执行时间1. gettimeofday精度1us #include<stdio.h>#include<sys/time.h> int main(){ /* 定义 ...

  10. poj-3682 King Arthur's Birthday Celebration

    C - King Arthur's Birthday Celebration POJ - 3682 King Arthur is an narcissist who intends to spare ...