Java中Class和单例类的作用与类成员的理解
Java中Class类的作用与深入理解
在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。JVM利用运行时信息选择相应的方法执行。而保存这些信息的类称为Class。可能容易产生混淆,容易想到class。不过二者没什么关系,class不过是描述类的一个关键字。而Class却是保存着运行时信息的类。
它能做什么?Class类可以帮助我们在程序运行时分析类,说白了就是获取类中的值。可能瞬间就想到了反射,没错!Class一般就是和反射配套使用的,因为我们向Class提供一个类或一个类的类名,Class就可以提供我们很多信息,比如属性/方法/修饰符/构造器/类名等等。然后我们就可以进一步进行反射。不过,还是先来简单了解下Class类的内容和使用方式吧!
获取Class对象的三种方式(实例采用Person类)
方式1:通过Object类的getObject()方法
Person p =newPerson();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);
}
}
classPerson{}
类成员的理解
类成员是属于整个类的,而不是属于对象的。因此创建一个对象时,只会为实例变量分配内存,而不会为类成员变量分配内存,类成员变量是在类初始化时分配的内存(执行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和单例类的作用与类成员的理解的更多相关文章
- java中安全的单例与不安全的单例
java中安全的单例与不安全的单例 1.内部静态类(安全的) public class Singleton { private static class SingletonHolder{ privat ...
- java 中的懒汉单例和饿汉单例模式
//-------------------------------------------------------------饿汉模式--开始----------------------------- ...
- Java中的懒汉式单例与饿汉式单例实例详解
懒汉式单例:线程非安全,当被调用的时候才创建实例,效率较高 public class LazySingleton { private static LazySingleton lazySingleto ...
- Java学习笔记之---单例模型
Java学习笔记之---单例模型 单例模型分为:饿汉式,懒汉式 (一)要点 1.某个类只能有一个实例 2.必须自行创建实例 3.必须自行向整个系统提供这个实例 (二)实现 1.只提供私有的构造方法 2 ...
- OC中两种单例实现方式
OC中两种单例实现方式 写在前面 前两天探索了一下C++ 的单例,领悟深刻了许多.今天来看看OC中的单例又是怎么回事.查看相关资料,发现在OC中一般有两种实现单例的方式,一种方式是跟C++ 中类似的常 ...
- Java中设计模式之单例设计模式-1
单例作用 1 节省内存 2 可以避免多种状态导致状态冲突 单例的创建步骤 1 私有化构造方法 2 私有化声明的属性 3 getInstance 4 方法需要静态 单例分类 1.懒汉式 2.饿汉式 两种 ...
- Java中创建操作文件和文件夹的工具类
Java中创建操作文件和文件夹的工具类 FileUtils.java import java.io.BufferedInputStream; import java.io.BufferedOutput ...
- Java中带包(创建及引用)的类的编译
Java中带包(创建及引用)的类的编译与调试 java源程序的编译大家都知道,也就是cmd中到源文件所在目录下javac **.java即可,当程序中有包声明还能简简单单的直接javac **.jav ...
- JAVA的设计模式之单例设计模式
1.确保一个类只有一个实例,自行提供这个实例并向整个系统提供这个实例. 1)理论 Java Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在. 使用Singl ...
随机推荐
- JVM GC算法 垃圾回收器
JVM的垃圾回收算法有三种: 1.标记-清除(mark-sweep):啥都不说,直接上图 2.标记-整理(mark-compact) 3.复制(copy) 分代收集算法 ...
- 201871010113-刘兴瑞《面向对象程序设计(java)》第十周学习总结
项目 内容 这个作业属于哪个课程 <任课教师博客主页链接> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>htt ...
- day91_11_13Local与偏函数
一.local 在线程的处理中,常常遇到这样的问题.当一系列线程遇到io操作的时候,就会执行其他线程,这时候就会出现数据冲突,发生数据方面的问题: from threading import Thre ...
- 史上最全的各种C++ STL容器全解析
史上最全的C++ STL 容器大礼包 为什么\(C++\)比\(C\)更受人欢迎呢?除了\(C++\) 的编译令人感到更舒适,\(C++\)的标准模板库(\(STL\))也占了很重要的原因.当你还在用 ...
- 加速自己的hexo,使用GitHub+Coding实现国内外网站加速
在配置好hexo之后,我们发现访问网站很慢,但又不是我们使用的主题的问题,那么就是网络环境的影响,即使我们使用了CDN加速,但还是没有我们国内的网站访问起来快速,(听说去美国的服务器要经过太平洋下面的 ...
- Educational Codeforces Round 76 (Rated for Div. 2) C. Dominated Subarray 水题
C. Dominated Subarray Let's call an array
- Pytorch的tensor数据类型
基本类型 torch.Tensor是一种包含单一数据类型元素的多维矩阵. Torch定义了七种CPU tensor类型和八种GPU tensor类型: Data tyoe CPU tensor GPU ...
- tensorflow2.0安装
版本: python3.5 Anaconda 4.2.0 tensorflow2.0 cpu版本 1.安装命令 pip3 install tensorflow==2.0.0.0a0 -i https: ...
- 《细说PHP》第四版 样章 第23章 自定义PHP接口规范 8
23.5.2 架构详解 本例的实现最重要的就是服务层的设计,有两个配置文件config.php和api.php,其中文件config.php是全局的配置文件,用于整个程序全局需要的参数设置.可以根据 ...
- nginx目录遍历漏洞复现
nginx目录遍历漏洞复现 一.漏洞描述 Nginx的目录遍历与apache一样,属于配置方面的问题,错误的配置可导致目录遍历与源码泄露. 二.漏洞原理 1. 修改nginx.conf,在如下图位置添 ...