黑马程序员——Java高级应用(一)

时间:2022-04-16 15:03:49

下面来介绍一下Java的高级应用有哪些。

Java高级应用

第一讲 类加载

(一).类加载

  类加载器是一个特殊的类,负责在运行时寻找和加载类文件。Java允许使用不同的类加载器,甚至是自定义类加载器。Java程序包含很多类文件,每一个都与单个Java类相对应,这些类文件随时需要随时加载。类加载器从源文件(通常是.class或.jar文件)获得不依赖平台的字节码,然后将它们加载到JVM内存空间,所以它们能被解释和执行。默认状态下,应用程序多的每个类由java.lang.ClassLoader加载。因为它可以被继承,所以可以*地加强其功能。

1.1  认识Class

  Java程序在运行时,运行时系统一直对所有的对象进行运行时类型标识,这项信息记录了每个对象所属的类。JVM通常使用运行时类型信息定位正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。

  JVM为每种类型管理一个独一无二的Class对像,即每个类(型)都有一个Class对象。运行程序时,JVM首先检查所要加载的类对应的Class对象是否已经加载,如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。

  Class无公共构造方法,其对象是在加载类时由JVM以及通过调用类加载器中的defineClass方法自动构造的,因此不能显示地声明一个Class对象。每个类都有一个class属性,可以直接以类.class方式访问,也可以通过实例访问,但实例获得class对象必须要调用getClass()方法才可以。

1.2  Class类的方法

  static Class forName(String name)————返回指定类名的Class对象(注意静态的)
  Object newInstance()————调用缺省构造方法,返回该Class对象的一个实例
  getName()————返回此Class对象所表示的实体(类、接口、数组、基本类型或void)名称
  Class []getInstance————获取当前Class对象的接口
  ClassLoader getClassLoader()————返回该类的加载器
  Class getSuperclass()————返回表示此Class所表示的实体的超类的Class

1.3  实践

  下面通过继承关系演示Class类的使用,首先定义Person类及其子类Student类。

 package com.itsuper.p1.classdemo;
public class Person {
String name;
//如果使用Class的newInstance()构造对象,则需要提供缺省的构造方法
public Person() { }
public Person(String name) {
this.name = name;
}
}
 package com.itsuper.p1.classdemo;
public class Student extends Person {
int age;
public Student() { }
public Student(String name, int age) {
super(name);
this.age = age;
}
}

  编写测试代码,使用Class类实现Student对象的创建

 package com.itsuper.p1.classdemo;

 public class ClassDemo {

     /**
* 演示Class类
* @param args
*/
public static void main(String[] args) {
String className = "com.itsuper.p1.classdemo.Student";
//因为调用forName()方法可能抛出异常,需要放到try中
try {
//调用静态方法forName()获取字符串对应的Class对象
Class c1 = Class.forName(className);
//构造一个对象,但是相应的构造类中必须提供缺省的构造函数,才能使用Class类的缺省构造方法
Object obj = c1.newInstance();
//通过类.class,获取Class实例
System.out.println(Student.class);
//通过具体对象,获取Class实例,但具体对象获取Class实例必须调用getClass()方法
System.out.println(obj.getClass().getName());
//判断类.class 与 具体对象获取Class实例是否是统一引用地址
if(obj.getClass()==Student.class){
System.out.println("The Class is Student class!");
}
System.out.println("----------------"); //获取当前Class对象的父类Class对象
Class superClass = c1.getSuperclass();
Object obj2 = superClass.newInstance();
System.out.println(obj2.getClass().getName()); //继续获取父类的Class对象
Class furtherClass = superClass.getSuperclass();
Object obj3 = furtherClass.newInstance();
System.out.println(obj3.getClass().getName()); } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

  运行结果:  

class com.itsuper.p1.classdemo.Student
com.itsuper.p1.classdemo.Student
The Class is Student class!
----------------
com.itsuper.p1.classdemo.Person
java.lang.Object

注意: 调用Class.froName(name)方法时,由于指定的类名可能不存在,需要将其放到try...catch语句块中

JVM为每种类型管理一个独一无二的Class对象。因此可以使用==操作符来比较类对象。通过运行结果分析,可以确定obj.getClass()和Student.class事实上是JVM管理的同一个Class对象。


 第二讲 ClassLoader

(二).  认识ClassLoader

  类装载器是用来把类(class)装载进JVM的。JVM规范定义了两种类型的类装载器:启动内装载器(bootstap)和用户自定义装载器(user-defined class loader).

自底向上检查类是否已装载

Bootstap Classloader 自顶向下尝试加载类
 
Extension Classloader
 
System Classloader

Bootstap(启动类加载器)是JVM自带的类装载器,负责装载Java平台核心类库,如java.lang.*等,在Java中看不到他,是null
Extension(扩展类加载器) 主要负责jdk_home/lib/ext目录下的jar包或—Djava.ext.dirs指定目录下的jar包装入工作
System(系统类加载器) 主要负责java-classpath/-Djava.class.path所指定的目录下的类与jar包装入工作

java提供了抽象类ClassLoader,所有用户自定义类装载器都实例化自ClassLoader的子类。ClassLoader是一个特殊的用户自定义类装载器,有JVM的实现者提供,如不特殊指定,其将作为系统缺省的装载器。

实践:

代码演示类加载机制的层次关系

 public class ClassLoaderDemo {
public static void main(String[] args){
ClassLoader classloader;
classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);//sun.misc.Launcher$AppClassLoader@1016632 while(classloader!=null){
classloader = classloader.getParent();
System.out.println(classloader);//sun.misc.Launcher$ExtClassLoader@dc6a77
// null
}//此过程在自底向上判断类加载器 try{
Class c1 = Class.forName("java.lang.Object");//返回Object的对象
classloader = c1.getClassLoader();//获得该对象的类加载器
System.out.println("java.lang.Object`s loader is " + classloader);
c1 = Class.forName("com.itsuper.p1.classdemo.ClassLoaderDemo");
classloader = c1.getClassLoader();
System.out.println("ClassLoaderDemo`s loader is " + classloader);
}catch (Exception e) {
System.out.println("Check name of the class");
}
}
}

  运行结果:

sun.misc.Launcher$AppClassLoader@1016632  //表示系统类加载器实例化自sun.misc.Launcher$AppClassLoader
sun.misc.Launcher$ExtClassLoader@dc6a77   //表示系统类装载器的parent实例化自类sun.misc.Launcher$ExtClassLoader
null                       //表示系统类加载器的parent的parent为bootstap,无法直接获取
java.lang.Object`s loader is null      //表示类Object是由bootstap装载的
ClassLoaderDemo`s loader is sun.misc.Launcher$AppClassLoader@1016632  //表示用户自己写的类是由系统类装载器装载的

2.1  加载过程

  ClassLoader加载类时,首先检查缓存中是否有该类
  (1)  若有直接返回
  (2)  若无,请求父类加载
  (3)  如果父类无法加载,则从bootstap classLoader加载

  然后加载指定类,搜索的顺序是:
  (1)  寻找class文件(从与此classloader相关的类路径中寻找)
  (2)  从文件载入class
  (3)  找不到则抛出ClassNotFoundException


第三讲 instanceof

 (三).  认识instanceof运算符

  Java的多态性机制导致了引用变量的声明类型和其实际引用的类型可能不一致,在结合动态方法调度机制可以得出结论:声明为同种类型的两个引用变量调用同一个方法时也可能会有不同的行为。为更准确的鉴别一个对象的真正类型,Java语言引入了instanceof操作符。

3.1  定义

  instanceof关键字是用于判断一个引用类型变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例。

3.2  使用格式

  <引用类型变量> instanceof <引用类型>

  注意:该表达式为Boolean类型的表达式,当instanceof左侧的引用类型变量所引入对象的实际类型是其右侧给出的类型或是其子类类型时,整个表达式的结果为true,否则为false。例如mi instanceof MyClass。

3.3  补充

  • 子类对象 instanceof 父类,返回true
  • 父类对象 instanceof 子类,返回false
  • 如果两个类不在同一继承家族中,是用instanceof时会出现错误
  • 数组类型也可以使用instanceof来比较

3.4  实践1

  下面通过继承关系来演示instanceof关键字的使用

 public class InstanceofDemo {

     public static void typeof(Object obj) {
if(obj instanceof Student){
System.out.println("Student!");
}
if(obj instanceof Person){
System.out.println("Person!");
}
}
public static void main(String[] args) {
Person pobj1 = new Person("tom");
Student sobj1 = new Student("Daming",5);
typeof(pobj1);
System.out.println("-------------------");
typeof(sobj1);
System.out.println("-------------------");
Person pobj2 = new Person("rose");
Student sobj2 = new Student("xiaoli",10);
typeof(pobj2);
System.out.println("-------------------");
typeof(sobj2);
System.out.println("-------------------");
String[] str = new String[2];
if(str instanceof String[]){
System.out.println("true! ");
}
}
}

  运行结果:

Person!
-------------------
Student!
Person!
-------------------
Person!
Student!
Person!
-------------------
true!

  通过对比结果,有什么发现呢?再仔细的品味一下 这句话吧!  “instanceof左侧的引用类型变量所引入对象的实际类型是其右侧给出的类型或是其子类类型时,整个表达式的结果为true”

实践2

定义一个接口IBase和两个类Derive,Derive1来演示instanceof用法

 //定义Interface接口IBase
interface IBase{
public void print();
} //定义Derive类实现IBase接口
class Derive implements IBase{
int b;
public Derive(int b) {
super();
this.b = b;
}
//实现接口的抽象方法
public void print(){
System.out.println("In Derive!");
}
} //定义Derive的子类Derive1
class Derive1 extends Derive{
int c;
public Derive1(int b, int c) {
super(b);
this.c = c;
}
public void print(){
System.out.println("In Derive1!");
}
} public class InstanceDemo2 {
//判断对象类型
public static void typeof(Object obj){
if(obj instanceof Derive){
Derive der = (Derive)obj;
der.print();
}else if(obj instanceof Derive1){
Derive1 der1 = (Derive1)obj;
der1.print();
}
} public static void main(String[] args) {
IBase b1 = new Derive(4);//父类引用指向子类对象
IBase b2 = new Derive1(4,5);
System.out.print("b1 is ");
//调用typeof()判断b1对象类型
typeof(b1);
System.out.print("b2 is ");
//调用typeof()判断b2对象类型
typeof(b2);
}
}
运行结果:
b1 is In Derive!
b2 is In Derive1!

黑马程序员——Java高级应用(一)的更多相关文章

  1. 【黑马18期Java毕业生】黑马程序员Java全套资料&plus;视频&plus;工具

        Java学习路线图引言:        黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...

  2. 黑马程序员Java基础班&plus;就业班课程笔记全发布(持续更新)

    正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G  QQ 1481135711 这是我总 ...

  3. 黑马程序员----java基础笔记中(毕向东)

    <p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...

  4. 黑马程序员——JAVA基础之泛型和通配符

    ------- android培训.java培训.期待与您交流! ---------- 泛型:            JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...

  5. 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象

    ------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...

  6. 黑马程序员——JAVA基础之语法、命名规则

    ------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...

  7. 黑马程序员——JAVA基础之JDK1&period;5新特性高级for循环和可变参数

    ------- android培训.java培训.期待与您交流! ---------- 高级for循环   格式: for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) {   ...

  8. 黑马程序员——JAVA基础之File类,递归,打印流,合并切割流

    ------- android培训.java培训.期待与您交流! ---------- File类 用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递 ...

  9. 黑马程序员——JAVA基础之多线程的安全问题

    ------- android培训.java培训.期待与您交流! ---------- 导致多线程出现问题的一个特殊的状态:就绪.具备了执行资格,但是还没有获取资源. 导致安全问题的出现的原因: 1. ...

随机推荐

  1. mysql Workbench 执行删除命令

    SET SQL_SAFE_UPDATES = 0;delete from table1; SET SQL_SAFE_UPDATES = 1;

  2. Linux 系统启动过程

    linux启动时我们会看到许多启动信息. Linux系统的启动过程并不是大家想象中的那么复杂,其过程可以分为5个阶段: 内核的引导. 运行init. 系统初始化. 建立终端 . 用户登录系统. 内核引 ...

  3. mac下python实现vmstat

    mac下没有linux/unix 的vmstat,只有vm_stat; sh-3.2# vm_statMach Virtual Memory Statistics: (page size of 409 ...

  4. 在特定的action里使用validates

    http://guides.rubyonrails.org/v3.0.8/active_record_validations_callbacks.html#on 在特定的action里使用valida ...

  5. 对于android触摸事件模型的一些理解

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  6. C&sol;C&plus;&plus;跨平台的的预编译宏

    我们在编译一些跨平台的程序的时候难免会遇到_WIN32  __linux__什么之类的SDK或者编译器环境预定义的宏.有很多,之前还分不清_WIN32 和WIN32的区别.不过这里还好有个列表,做个备 ...

  7. Shell 编程注意点

    (一)判断语句 [$# -lt 4 ]判断语句,格式[空格 比较对象1 比较符号 比较对象2] $# 启动脚本时携带参数个数;参数个数总数. $1 代表第一个参数. $? 最后一次执行名命令的退出状态 ...

  8. RS-485总线通信协议

    https://blog.csdn.net/ouyangxin95/article/details/78174145 RS-485总线技术只是规定了接口的电气标准,并没有规定RS-485接口的电缆,插 ...

  9. 对象关系映射&lpar;ORM&rpar;框架GreenDao简介和基本使用

    官网上的介绍,greenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案. GreenDao特点 性能最大化,可能是Android平台上最快的ORM框架 易于使用的A ...

  10. 【Tomcat】CentOS7&period;0下安装多个Tomcat及其配置

    安装前所需环境 在开始安装Tomcat之前,需要安装环境JDK,并配置JAVA环境.如果不知道如何配置,可参考这篇博客:[Linux]CentOS7.0下安装JDK环境 Tomcat安装 Tomcat ...