当前位置: 首页 > news >正文

半路出家去学计算机网站开发福州网站关键词推广

半路出家去学计算机网站开发,福州网站关键词推广,西北电力建设甘肃工程公司网站,asp做的网站怎么运行一. Object类介绍 java.lang.Object类是所有类的父类#xff0c;每个类都使用 Object 作为超类。所有对象#xff08;包括数组#xff09;都实现这个类的方法。在不明确给出超类的情况下#xff0c;Java会自动把Object作为要定义类的超类。可以使用类型为Object的变量指向任…一. Object类介绍 java.lang.Object类是所有类的父类每个类都使用 Object 作为超类。所有对象包括数组都实现这个类的方法。在不明确给出超类的情况下Java会自动把Object作为要定义类的超类。可以使用类型为Object的变量指向任意类型的对象。 Object类提供了多个方法具体如下 public Object()public final native Class? getClass()public native int hashCode()public boolean equals(Object obj)public String toString()protected native Object clone()public final native void notify()public final native void notifyAll()public final native void wait(long timeout)public final void wait(long timeout, int nanos)public final void wait()protected void finalize() 下面笔者将详细介绍这些重要的方法。 二. 方法详细介绍 1. public Object()       这个方法是Object类的一个默认的构造方法在构造子类时都会先调用这个默认构造方法。 2. public final native Class? getClass() getClass()方法是一个final方法这就意味着不允许子类重写同时这也是一个native方法。 getClass()返回该对象的运行时类的 java.lang.Class 对象该对象保存着原对象的类信息比如原对象的类名叫什么类里有什么方法字段等这些信息可以由Class对象的getName()、getMethods()等方法获取。该方法返回值为Class对象后面的“”是泛型“”则属于类型通配符的一种代表着正在运行的类。 这里笔者只是简单介绍Object类getClass()的作用而Class对象更多的是与反射联系在一起关于反射的内容请查看其它相关的资料。       3. public native int hashCode() hashCode()方法同样是一个native方法该方法返回对象的哈希码值。hashCode是用来在散列存储结构中确定对象的存储地址的在HashMap、Hashtable等底层实现都有用到其主要是用于查找的快捷性因为在集合查找时hashcode能大大降低对象比较次数提高查找效率。 关于hashCode有几点常规的约定       ① 在 Java 应用程序执行期间在同一对象上多次调用 hashCode 方法时必须一致地返回相同的整数前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行该整数无需保持一致。       ② 如果根据 equals(Object) 方法判定两个对象是相等的那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。       ③ 如果根据equals方法得到两个对象不相等那么这2个对象的hashCode值不需要必须不相同即可以相同。但是不相等的对象的hashCode值不同的话可以提高哈希表的性能。       ④当equals方法被重写时通常有必要重写 hashCode 方法以维护 hashCode 方法的常规协定。 实际上由于hashCode一般是通过将该对象的内部地址转换成一个整数来实现的所以通常情况下不同的对象产生的哈希码是不同的。 public class User {private String name;private int sex;private String address;public User(String name, int sex, String address) {super();this.name name;this.sex sex;this.address address;}Overridepublic int hashCode() {final int prime 31;int result 1;result prime * result ((address null) ? 0 : address.hashCode());result prime * result ((name null) ? 0 : name.hashCode());result prime * result sex;return result;}Overridepublic boolean equals(Object obj) {if (this obj)return true;if (obj null)return false;if (getClass() ! obj.getClass())return false;User other (User) obj;if (address null) {if (other.address ! null)return false;} else if (!address.equals(other.address))return false;if (name null) {if (other.name ! null)return false;} else if (!name.equals(other.name))return false;if (sex ! other.sex)return false;return true;} } 这个例子给出User类有三个属性name、sex和address。使用Eclipse自动生成hashCode()和equals() 方法如上。我们先跳过equals()方法直接看 hashCode()方法实现。从上面的代码可以看到hashCode()方法首先声明一个值为31的整型变量然后遍历所有的类属性累加计算result31*resultA若A是整型数直接相加若是String类型调用String类的hashCode()方法其他类型具体实现可自己自动生成hashCode()方法查看这里笔者只简单讲下String类型然后String类的hashCode()实现如下 public int hashCode() { int h hash; if (h 0 value.length 0) { char val[] value; for (int i 0; i value.length; i) { h 31 * h val[i]; } hash h; } return h; } 上面的代码其实做的就是计算s[0]*31^(n-1) s[1]*31^(n-2) ... s[n-1]的值 s[i]是string的第i个字符n是String的长度。那么问题来了为什么上面的User类还有这里的String类都使用31做乘数而不是用其他数呢主要有两个原因①之所以选择31是因为它是个奇素数。如果乘数是偶数并且乘法溢出的话信息就会丢失因为与2相乘等价于移位运算。使用素数的好处并不是很明显但是习惯上都使用素数来计算散列结果。②31有个很好的特性就是用移位和减法来代替乘法可以得到更好的性能31*i(i5)-i。       因此hashCode()方法的实现通常使用31来作乘数同时方法体里遍历所有值来累加得到hashCode的实现能够导致相同的value就一定有相同的hashCode不同的value也较大可能得到不同的hashCode但这不是一定的不同的value还是有可能有相同的hashCode的。至于为什么要使用累加得到hashCode这么复杂的实现就需要数学家来解释了。 4. public boolean equals(Object obj) equals()方法用来比较两个对象是否相等默认实现是使用“”直接比较即比较两个对象的内存地址是否相等: public boolean equals(Object obj) { return (this obj); } equals方法在非空对象引用上有以下特性       ①reflexive 自反性。任何非空引用值x对于x.equals(x)必须返回true。       ②symmetric 对称性。任何非空引用值x和y如果x.equals(y)为true那么y.equals(x)也必须为true。       ③transitive 传递性。任何非空引用值x、y和z如果x.equals(y)为true并且y.equals(z)为true那么x.equals(z)也必定为true。       ④consistent 一致性。任何非空引用值x和y多次调用 x.equals(y) 始终返回 true 或始终返回 false前提是对象上 equals 比较中所用的信息没有被修改。       对于任何非空引用值 xx.equals(null) 都应返回 false。 equals()比较容易理解所以就不多说了。不过需要注意的是如果重写了equals()方法通常有必要重写hashCode()方法这一点已经在上面已经讲过了。 5. public String toString() toString()方法是用来放回一个简明易懂的“以文本方式表示”的字符串建议Object所有的子类都重写这个方法。默认实现如下 public String toString() { return getClass().getName() Integer.toHexString(hashCode()); } 可以看到Object 类的 toString() 方法返回一个字符串该字符串由类名对象是该类的一个实例、at 标记符“”和此对象哈希码的无符号十六进制表示组成。 6. protected native Object clone()       clone()方法创建并返回此对象的一个拷贝。一般情况下对于任何对象 x表达式 x.clone() ! x 为truex.clone().getClass() x.getClass() 也为true。 由于Object 类本身不实现接口 Cloneable所以在类为 Object 的对象上调用 clone() 方法将会导致在运行时抛出异常CloneNotSupportedException。同时如果Object的子类没有实现接口 Cloneable调用clone()方法同样会抛出CloneNotSupportedException以指示无法克隆某个实例。 来到这里可能有人会问为什么需要克隆对象直接new一个对象不行吗答案是因为克隆的对象可能包含一些已经修改过的属性而new出来的对象的属性都还是初始化时候的值所以当需要一个新的对象来保存当前对象的“状态”就靠clone()方法了。那么我把这个对象的临时属性一个一个的赋值给我新new的对象不也行吗可以是可以但是一方面这比较麻烦另一方面。我们可以看到clone()方法是native方法毫无疑问这速度快因为实在底层实现的。 要理解好clone()方法先要知道深度克隆以及浅度克隆。我们知道如果要实现克隆需要实现Cloneable接口然后重写clone()方法。我们调用clone()方法想的是先在内存中开辟一块和原始对象一样的空间然后原样拷贝原始对象中的内容。如果我们重写clone()方法是只是单单调用super.clone()对于基本数据类型这样的操作是没有问题的但对于非基本类型变量比如依赖其他的类这样实现其实clone的对象保存的只是原对象的引用这导致clone后的非基本类型变量和原始对象中相应的变量指向的是同一个对象。这就是浅度克隆。 public class User implements Cloneable {private String name;private int sex;private String address;public User(String name, int sex, String address) {super();this.name name;this.sex sex;this.address address;}Overrideprotected Object clone() throws CloneNotSupportedException {// TODO Auto-generated method stubreturn super.clone();}public static void main(String[] args) {User u1 new User(Jack, 1, USA);try {User u2 (User) u1.clone();System.out.println(u1.name u2.name);} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}} 上面的程序输出是true证明默认调用super.clone()浅度克隆得到的是原对象的引用。       其实我们的初衷是对于要克隆的对象中的非基本数据类型的属性对应的类也要实现克隆这样对于非基本数据类型的属性复制的不是一份引用即新产生的对象和原始对象中的非基本数据类型的属性指向的不是同一个对象这就是深度克隆。 要实现深度克隆对于有非基本数据类型的属性的类在clone时除了实现Cloneable接口调用super.clone()方法对于非基本数据类型就需要再在该属性上调用一次clone()方法 class Address implements Cloneable {private String address;public Address(String address) {super();this.address address;}Overrideprotected Object clone() throws CloneNotSupportedException {// TODO Auto-generated method stubreturn super.clone();} }public class User implements Cloneable {private String name;private int sex;private Address address;public User(String name, int sex, Address address) {super();this.name name;this.sex sex;this.address address;}Overrideprotected Object clone() throws CloneNotSupportedException {User u (User) super.clone();u.address (Address) this.address.clone();return u;}public static void main(String[] args) {Address add new Address(China);User u1 new User(Jack, 1, add);try {User u2 (User) u1.clone();System.out.println(u1.address u2.address);} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace();}} } 上面的例子中要实现User类的深度克隆可以看到User类的clone()方法除了需要调用super.clone()还需要在非基本数据类型Address上调用clone()方法当然了Address也得实现Cloneable接口。这样才能真正实现深度克隆上面代码执行的结果才会是false。       clone()方法还有一个需要注意的地方就是clone()方法是一个protected属性的方法。为什么Object类要将clone()方法定义为protected而不是public呢其实使用protected来修饰clone()方法是为了安全考虑。从上面我们已经了解了深度拷贝和浅度拷贝的定义以及区别当当前的类依赖于其他类即有非基本数据类型的属性后Object类无法帮我们实现深度拷贝将修饰符定义为protected这样想要在其他任何地方调用这个类的clone()方法时这个类就必须去重写clone()方法并且把修饰符改为public这样在任何地方都可以调用这个类的clone()方法了。比如下面的例子 package com; public class A { } package org; import com.A; public class B { public static void main(String[] args) { A a new A(); a.clone(); } } 如上面的例子类A是要被克隆的类类B相当于要使用A的地方如果类A不重写clone方法在B类中是调不到clone()方法的因为A和B既不是子父类关系也不在同一个包下所以clone()方法对B是不可见的。当类A实现Cloneable接口并且重写clone()方法后clone()方法在B类中就可见了也就是说我们在任何地方都可以克隆A了。       总而言之用protected修饰clone()方法主要是为了让子类去重写它实现深拷贝以防在其他任何地方随意调用后修改了对象的属性对原来的对象造成影响。如果使用public修饰clone()方法子类就不用必须重写clone()方法这样就可能会出现问题。 7. public final native void notify() 首先看到notify()方法是一个native方法并且也是final的不允许子类重写。 notify()唤醒在此对象监视器上等待的单个线程。如果所有线程都在此对象上等待则会选择唤醒其中一个线程。选择是任意性的并在对实现做出决定时发生。线程通过调用其中一个 wait ()方法在对象的监视器上等待。 直到当前的线程放弃此对象上的锁定才能继续执行被唤醒的线程。被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争。例如唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。 notify()方法只能被作为此对象监视器的所有者的线程来调用。一个线程要想成为对象监视器的所有者可以使用以下3种方法①执行对象的同步实例方法②使用synchronized内置锁③对于Class类型的对象执行同步静态方法。 需要注意的是一次只能有一个线程拥有对象的监视器。如果当前线程不是此对象监视器的所有者的话会抛出IllegalMonitorStateException异常。 8. public final native void notifyAll() notifyAll()方法跟上面的notify()一样不同的是notifyAll()是唤醒在此对象监视器上等待的所有线程。       同样的如果当前线程不是对象监视器的所有者那么调用notifyAll同样会发生IllegalMonitorStateException异常。 9. public final native void wait(long timeout) 该方法导致当前的线程等待直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法或者超过指定的时间量。当前的线程必须拥有此对象监视器否则还是会发生IllegalMonitorStateException异常。 该线程发布对此监视器的所有权并等待直到其他线程通过调用 notify ()方法或 notifyAll() 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。 wait()方法会让当前线程(比如线程T)将其自身放置在对象的等待集中并且放弃该对象上的所有同步要求。出于线程调度目的线程T是不可用并处于休眠状态直到发生以下四件事中的任意一件       ①其他某个线程调用此对象的notify()方法并且线程T碰巧被任选为被唤醒的线程       ②其他某个线程调用此对象的notifyAll()方法       ③其他某个线程调用Thread.interrupt()方法中断线程T       ④时间到了参数设置的超时时间。如果timeout参数为0则不会超时会一直进行等待。 可以理解wait()方法相当于放弃了当前线程对对象监视器的所有者(也就是说释放了对象的锁)之后线程T会被等待集中被移除并且重新进行线程调度。然后该线程以常规方式与其他线程竞争以获得在该对象上同步的权利。一旦获得对该对象的控制权该对象上的所有其同步声明都将被恢复到以前的状态这就是调用wait方法时的情况。然后线程T从wait方法的调用中返回。所以从wait方法返回时该对象和线程T的同步状态与调用wait方法时的情况完全相同。 在没有被通知、中断或超时的情况下线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup)。虽然这种情况在实践中很少发生但是应用程序必须通过以下方式防止其发生即对应该导致该线程被提醒的条件进行测试如果不满足该条件则继续等待。换句话说等待应总是发生在循环中如下面的示例 synchronized (obj) { while (condition does not hold) obj.wait(timeout); ... // Perform action appropriate to condition } 如果当前线程在等待之前或在等待时被任何线程中断则会抛出InterruptedException异常。在按上述形式恢复此对象的锁定状态时才会抛出此异常。 10. public final void wait(long timeout, int nanos)        跟wait(long timeout)方法类似多了一个nanos参数这个参数表示额外时间以毫微秒为单位范围是 0-999999。 所以超时的时间还需要加上nanos毫秒。 需要注意的是 wait(0, 0)和wait(0)效果是一样的即一直等待。 11. public final void wait() wait()方法导致当前的线程等待直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。换句话说此方法的行为就好像它仅执行 wait(0) 调用一样。 一般情况下wait()方法和notify()方法会一起使用的wait()方法阻塞当前线程notify()方法唤醒当前线程。一个使用wait()和notify()方法的生产者消费者例子代码如下 public class WaitNotifyTest {public static void main(String[] args) {Factory factory new Factory();new Thread(new Producer(factory, 5)).start();new Thread(new Producer(factory, 5)).start();new Thread(new Producer(factory, 20)).start();new Thread(new Producer(factory, 30)).start();new Thread(new Consumer(factory, 10)).start();new Thread(new Consumer(factory, 20)).start();new Thread(new Consumer(factory, 5)).start();new Thread(new Consumer(factory, 5)).start();new Thread(new Consumer(factory, 20)).start();}}class Factory {public static final Integer MAX_NUM 50;private int currentNum 0;public void consume(int num) throws InterruptedException {synchronized (this) {while(currentNum - num 0) {this.wait();}currentNum - num;System.out.println(consume num , left: currentNum);this.notifyAll();}}public void produce(int num) throws InterruptedException {synchronized (this) {while(currentNum num MAX_NUM) {this.wait();}currentNum num;System.out.println(produce num , left: currentNum);this.notifyAll();}}}class Producer implements Runnable {private Factory factory;private int num;public Producer(Factory factory, int num) {this.factory factory;this.num num;}Overridepublic void run() {try {factory.produce(num);} catch (InterruptedException e) {e.printStackTrace();}} }class Consumer implements Runnable {private Factory factory;private int num;public Consumer(Factory factory, int num) {this.factory factory;this.num num;}Overridepublic void run() {try {factory.consume(num);} catch (InterruptedException e) {e.printStackTrace();}} } 12. protected void finalize()       当垃圾回收器确定不存在对该对象的更多引用时由对象的垃圾回收器调用此方法。 finalize()方法是一个protected方法Object类的默认实现是不进行任何操作。子类需要重写 finalize ()方法以配置系统资源或执行其他清除。 finalize 的常规协定是当 Java虚拟机已确定尚未终止的任何线程无法再通过任何方法访问此对象时将调用此方法除非由于准备终止的其他某个对象或类的终结操作执行了某个操作。finalize() 方法可以采取任何操作其中包括再次使此对象对其他线程可用不过finalize()的主要目的是在不可撤消地丢弃对象之前执行清除操作。 finalize ()方法执行非特殊性操作它仅执行一些常规返回。Object 的子类可以重写此定义。Java 不保证哪个线程将调用某个给定对象的 finalize 方法但可以保证在调用 finalize()时调用 finalize()的线程将不会持有任何用户可见的同步锁定。如果 finalize()方法抛出未捕获的异常那么该异常将被忽略并且该对象的终结操作将终止。 在启用某个对象的 finalize() 方法后将不会执行进一步操作直到 Java 虚拟机再次确定尚未终止的任何线程无法再通过任何方法访问此对象其中包括由准备终止的其他对象或类执行的可能操作在执行该操作时对象可能被丢弃。 对于任何给定对象Java 虚拟机最多只调用一次 finalize() 方法。
http://www.zqtcl.cn/news/971851/

相关文章:

  • 洛阳网站建设优惠公司做网站用虚拟主机还是服务器
  • 做自媒体网站需要注册什么公司六安app开发公司
  • 怎么用服务器ip做网站网站建设公司如何发展
  • 网站定位策划制作英文网站案例
  • 台州网站平面设计家装设计学校
  • 做PPT的辅助网站网站建设费属于宣传费吗
  • 湖南网站seo地址北京网站制作公司有哪些
  • 国内最佳网站建设设计emlog转移到wordpress
  • 网站优化怎么做效果才好网络营销工程师
  • 网站微信建设运维经验分享做个网站得多少钱
  • 网站开发设计制作合同静态营销网站代码
  • 中山自助建站系统网站 建设运行情况报告
  • 江西省城乡建设培训网官方网站什么叫静态网站
  • 用vue做网站的实例500个短视频素材免费
  • 免代码开发平台郴州做网站seo
  • 寻找网站设计与制作网站建设不包括以下哪个阶段
  • 网站建设服务合同范本电子商务和网站建设方案
  • 企业做电商网站有哪些内容建站展示
  • 网站建设服务58产品软文范例
  • 建设网站具备的知识丽水做网站公司
  • 宁波网站排名优化公司手机网站 点击打开
  • 网站制作的网站学会网站制作要多久
  • 苏州网站建设外包哪个网站公司做的
  • 深圳展示型网站建设推广什么app佣金高
  • 鹤壁市住房和城乡建设局网站设计一个电子商务网站
  • 无线路由器做中继手机能连接但无法访问网站做一个游戏需要什么技术
  • 如何创建自己的网站建设网站收取广告费用
  • 商务咨询网站源码光做网站推广咋样
  • 重庆 做网站酷站网素材
  • 商城网站建设公司价格海安县建设局网站