黑马程序员——Java高级应用(一)
下面来介绍一下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高级应用(一)的更多相关文章
- 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具
Java学习路线图引言: 黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...
- 黑马程序员Java基础班+就业班课程笔记全发布(持续更新)
正在黑马学习,整理了一些课程知识点和比较重要的内容分享给大家,也是给自己拓宽一些视野,仅供大家交流学习,大家有什么更好的内容可以发给我 ,现有黑马教程2000G QQ 1481135711 这是我总 ...
- 黑马程序员----java基础笔记中(毕向东)
<p>------<a href="http://www.itheima.com" target="blank">Java培训.Andr ...
- 黑马程序员——JAVA基础之泛型和通配符
------- android培训.java培训.期待与您交流! ---------- 泛型: JDK1.5版本以后出现新特性.用于解决安全问题,是一个类型安全机制. 泛型好处: ...
- 黑马程序员——JAVA基础之简述面向对象,类,变量,匿名对象
------- android培训.java培训.期待与您交流! ---------- 面向对象: 面向对象是相对面向过程而言 面向对象和面向过程都是一种思想 面向过程 强调的是功能行为 面向对象 将 ...
- 黑马程序员——JAVA基础之语法、命名规则
------- android培训.java培训.期待与您交流! ---------- 1.java语言组成:关键字,标识符,注释,常量和变量,运算符,语句,函数,数组. 2.java关键字:被Jav ...
- 黑马程序员——JAVA基础之JDK1.5新特性高级for循环和可变参数
------- android培训.java培训.期待与您交流! ---------- 高级for循环 格式: for(数据类型 变量名 : 被遍历的集合(Collection)或者数组) { ...
- 黑马程序员——JAVA基础之File类,递归,打印流,合并切割流
------- android培训.java培训.期待与您交流! ---------- File类 用来将文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作. File对象可以作为参数传递 ...
- 黑马程序员——JAVA基础之多线程的安全问题
------- android培训.java培训.期待与您交流! ---------- 导致多线程出现问题的一个特殊的状态:就绪.具备了执行资格,但是还没有获取资源. 导致安全问题的出现的原因: 1. ...
随机推荐
- Android入门1:使用VideoView和MediController播放视频
最近在搞Android,入门曲线还是挺陡峭的,主要还是自己对Java的理解不够深入.前后学习了几天,把最近学习到的一些知识点总结归纳一下,正所谓温故而知新. 目前想搞一个禁播视频站,主要内容都是一些大 ...
- 【转】C++成员函数的存储方式
[转] http://c.biancheng.net/cpp/biancheng/view/187.html 用类去定义对象时,系统会为每一个对象分配存储空间.如果一个类包括了数据和函数,要分别为数据 ...
- Sicily 1156. Binary tree
题目地址:1156. Binary tree 思路: 如何愉快地前序输出呢,要在存储数据的时候根据位置来存放数据! 一开始被自己蠢哭,一直以为第一个输入的就是根结点(例子的祸害呀啊啊啊!!!!),结果 ...
- linux int to string 方法
最近从windows 移植程序的时候发现to_string()函数在linux 中不能用,网上找了几种方法,觉得使用stringstream对象来实现类型转化比较好一点. 你只需在你工程中加入下面的t ...
- uva 10929 - You can say 11
#include <cstdio> using namespace std; ]; int main() { while(gets(in)) { ] == ] == ) break; ; ...
- sql_autoload_register() 函数 和__autoload() 的区别
1:__autoload($class) 因为是一个函数,所以只能定义一次,使用多个会冲突报错;而 sql_autoload_register('function') 可定义多个,它有效地创建一个队列 ...
- struts2中<s:select/>标签的运用详解
<s:select list="smsTypes" listKey="SmsTypeId" listValue="SmsTypeName&quo ...
- php 之 注册审核(0523)
当注册后,先将信息保存到session,通过审核后才会添加到数据库中, 审核通过后状态变为已通过,这时添加到数据库中的信息进行登录.若发现此用户的不良行为,可以撤销通过. 注册页面: <!DOC ...
- Vim的snipMate插件
介绍终于发现了一个插件,对于Vim下代码块的自动补全支持的很好.给大家推荐snipMate. snipMate可以帮助您在vim上实现类似Textmate的功能,自动代码块的能力非常强大,而且代码块是 ...
- Flask学习记录之MarkDown编辑文本
为了让网页支持markdown编辑文本,使用如下了4个库 PageDown : 在前端提供一个可以实时将markdown内容转换成html文本进行效果预览的编辑器 Flask-PageDown: 这个 ...