316

http://blog.csdn.net/ch1406285246/article/details/55504330

https://www.cnblogs.com/carlos-mm/p/6297197.html

https://pan.baidu.com/s/1tjOD7dqZPfzFZKUPkhPegg

 https://www.cnblogs.com/gdayq/p/5797645.html

tcpdump -n -s 0 -w 1.cap ip host XXXX and port 5000

route add -net xxxxx netmask xxxxxx gw xxxxxx eth0

http://blog.csdn.net/bjyfb/article/details/6682913

https://www.cnblogs.com/wangning528/p/6388464.html

https://www.cnblogs.com/ranyonsue/p/5984001.html

实例:

new 一个对象是实例吗?
对,是实例,你说的没错。可以把这个new出来的对象叫做实例,说白了就是这个new出来的“东西”,叫它对象也可以,叫它实例也可以,对象和实例在这个角度上来讲是等价的。
这样:
Java中使用 new关键字 加上 构造方法,来创建一个对象,下面是一个名为Cat的类,
public class Cat {
public Cat() {
System.out.println("这是构造方法");
}
}
使用new + 构造方法 来创建一个对象,那么也就是
Cat c = new Cat();
前半部分,Cat c 的意思是,在内存中分配一个变量,名字叫c,这个变量是Cat类型的,它的值是什么?
一会儿在说;
后半部分,new Cat(); 这就是new关键字和构造方法来创建一个对象,Cat()是构造方法的名字没错吧?想造出一个对象来,就这么写,语法规定的,没有为什么;
new Cat(); 说明 new这个Cat类的一个对象,程序运行的时候,会调用构造方法Cat(),等这个构造方法执行完了,这个Cat类型的对象也就造出来了,真正的出现在内存当中了;
使用new关键字造出来的对象,被分配在内存的堆区(heap),而且等这个对象真正出来之后,还会做一件重要的事情:
我们这个对象是被分配在内存中的,那么内存地方大了,这个对象在哪里呢?怎么找到它呢?new关键字创建出一个对象之后,会把这个对象在内存中的地址返回,通过这个地址就可以找到这个对象,那么我们上面的写法,
Cat c = new Cat();
意思就是说,把这个对象在内存中的地址 赋值 给变量c,这就是Java中引用概念,c就叫做引用,或者叫引用变量,或者直接叫变量,没问题,都是它;
c的值就是一个内存地址,或者叫引用地址,通过这个地址,就可以准确的找到我们刚才创建出来的对象,以后我们要使用这个对象做一些事情,调用此对象的方法什么的,都用过这个引用,ok?
----
注意,我再说一遍,好多人都搞不清楚,这个c到底是对象还是引用,好多人说c就是Cat类的一个实例,这是非常错误的,c就是引用,不是对象!我们new出来的这个东西,真正在内存中的这个东西叫做对象,叫做实例

实例变量(instance variable):或叫实例域、实例字段(instance field),或叫成员变量(member variable)。实例的变量,每个实例的变量可能不同。实例方
法(instance method):或叫成员方法(member method)。供实例用的方法,必须要先有实例,才能通过此实例调用实例方法。类变量(class variable):或叫静
态域、静态字段(static field),或叫静态变量(static variable)。出现在这样的情况下:一个类的所有实例需要一个公有的属性,比如,一,统计实
例个数;二,常量。类变量与类直接关联在一起。内存当中只有一个地方存放这个变量。任何实例都可以修改它的值(前提是它没有被final修饰符修饰,不然就是常
量),但是,访问类变量并不需要实例,用类就可以操作了。类方法(class method):跟类变量的基本特点一样。供类用的方法,可以没有实例,直接通过类来调
用类方法。从形式上看,类变量和类方法,比一般的变量和方法多了一个static修饰符。因为这个原因,类变量和类方法也被叫做静态变量和静态方法。它们的使
用方法:实例方法可以直接访问实例变量,调用实例方法; 实例方法可以直接访问类变量,调用类方法。但不推荐这么做,原因是不清晰,容易把类变量误认
为是实例变量,把类方法误认为是实例方法(借助IDE,它会给出警告信息。); 类方法可以直接调用类变量和类方法; 类方法不能直接调用实例变量和实例方法; 类方法里
面不能使用“this”关键字,因为没有实例存在,“this”不知道引用哪个实例。
实例就是对象
实例变量:在用该类创建对象时才在会出现并被赋值。
类变量(静态变量):在该类加载到VM中时就被赋值,且该变量被这个类的所有对象所共享。
同一类的不同的对象有自己的实例变量,但是它们共享同一个类变量。当一个对象修改了它的实例变量时,不会影响其他的对象各自的实例变量。如果一个对象修改了类变量,则对于其他对象来说这个值也被改变了
创建对象
实例就是某个类的一个对象。

类只是一个抽象的东西,对象才是实在的东东。所以叫实例


枚举:
如果一个类中有私有方法,那么该类是否不能外部去访问呢?、
枚举简单的说也是一种数据类型,只不过是这种数据类型只包含自定义的特定数据,它是一组有共同特性的数据的集合。
举个例子,颜色也可以定义成枚举类型,它可以包含你定义的任何颜色,当需要的时候,只需要通过枚举调用即可,
另外比如说季节(春夏秋冬)、星期(星期一到星期日)等等这些具有共同投特征的数据都可以定义枚举。

 -----------------------------------------------------------------------------------------------------------------------------------------

强制类型转换:

在java中强制类型转换分为基本数据类型和引用数据类型两种,这里我们讨论的后者,也就是引用数据类型的强制类型转换。

在Java中由于继承和向上转型,子类可以非常自然地转换成父类,但是父类转换成子类则需要强制转换。因为子类拥有比父类更多的属性、更强的功能,所以父类转换为子类需要强制。那么,是不是只要是父类转换为子类就会成功呢?其实不然,他们之间的强制类型转换是有条件的。

当我们用一个类型的构造器构造出一个对象时,这个对象的类型就已经确定的,也就说它的本质是不会再发生变化了。在Java中我们可以通过继承、向上转型的关系使用父类类型来引用它,这个时候我们是使用功能较弱的类型引用功能较强的对象,这是可行的。但是将功能较弱的类型强制转功能较强的对象时,就不一定可以行了。

举个例子来说明。比如系统中存在Father、Son两个对象。首先我们先构造一个Son对象,然后用一个Father类型变量引用它:

Father father = new Son();

在这里Son 对象实例被向上转型为father了,但是请注意这个Son对象实例在内存中的本质还是Son类型的,只不过它的能力临时被消弱了而已,如果我们想变强怎么办?将其对象类型还原!

Son son = (Son)father;

这条语句是可行的,其实father引用仍然是Father类型的,只不过是将它的能力加强了,将其加强后转交给son引用了,Son对象实例在son的变量的引用下,恢复真身,可以使用全部功能了。

前面提到父类强制转换成子类并不是总是成功,那么在什么情况下它会失效呢?

当引用类型的真实身份是父类本身的类型时,强制类型转换就会产生错误。例如:

Father father = new Father();

Son son = (Son) father;

这个系统会抛出ClassCastException异常信息。

所以编译器在编译时只会检查类型之间是否存在继承关系,有则通过;而在运行时就会检查它的真实类型,是则通过,否则抛出ClassCastException异常。

所以在继承中,子类可以自动转型为父类,但是父类强制转换为子类时只有当引用类型真正的身份为子类时才会强制转换成功,否则失败。

------------------------------------------------------

判断变量类型:

对象 instanceof 类
obj instanceof class
如果class obj1 = obj成立的话,返回true,否则返回false

类.isInstance(对象)
class.isInstance(obj)
如果class obj1 = obj成立的话,返回true,否则返回false

看到更形象的解释

instanceof运算符 只被用于对象引用变量,检查左边的被测试对象 是不是 右边类或接口的 实例化。如果被测对象是null值,则测试结果总是false。
形象地:自身实例或子类实例 instanceof 自身类 返回true
例: String s=new String("javaisland");
System.out.println(s instanceof String); //true

Class类的isInstance(Object obj)方法,obj是被测试的对象,如果obj是调用这个方法的class或接口 的实例,则返回true。这个方法是instanceof运算符的动态等价。
形象地:自身类.class.isInstance(自身实例或子类实例) 返回true
例:String s=new String("javaisland");
System.out.println(String.class.isInstance(s)); //true

Class类的isAssignableFrom(Class cls)方法,如果调用这个方法的class或接口 与 参数cls表示的类或接口相同,或者是参数cls表示的类或接口的父类,则返回true。
形象地:自身类.class.isAssignableFrom(自身类或子类.class) 返回true
例:System.out.println(ArrayList.class.isAssignableFrom(Object.class)); //false
System.out.println(Object.class.isAssignableFrom(ArrayList.class)); //true

经检验,网上很多用instanceof直接判断的方法是行不通的。我总结出两种方法。
以判断变量是否为int为例,直接上代码。

方法一:
public class test {
public static void main(String[] args)
{
test t=new test();
int int_num=0;
double double_num=0;
System.out.println(t.judgeType(int_num));
System.out.println(t.judgeType(double_num));
}
public boolean judgeType(Object temp)
{ if(temp instanceof Integer)
return true;
else return false;
} }


方法二:
public class test {
public static void main(String[] args
{
try
{


Scanner input=new Scanner(System.in);
int i=input.nextInt(); System.out.println("输入正确");
} catch(Exception e){ System.out.println("输入错误");
} } }

方法一使用的是instanceof运算符,利用基本数据类型与其包装类自动转换的特点,运用多态,达到判断基本数据类型的目的。
方法二是运用异常处理的知识。较为巧妙。

例子:
class A{

}

class B extends A {

}

class C extends B {

}


public class tt {

/**
* @param args
*/

public static void main(String[] args) {
// TODO Auto-generated method stub
C c = new C();
B b = new B();
A a = new A();

B bc = new C();
A ac = new C();

System.out.println(c instanceof C);
System.out.println(c instanceof B);
System.out.println(c instanceof A);

System.out.println();

System.out.println(c.getClass().isInstance(c));
System.out.println(c.getClass().isInstance(b));
System.out.println(c.getClass().isInstance(a));

System.out.println();

System.out.println(c.getClass().isInstance(bc));
System.out.println(c.getClass().isInstance(ac));

System.out.println();

System.out.println(A.class.isInstance(a));
System.out.println(A.class.isInstance(b));
System.out.println(A.class.isInstance(c));
System.out.println(A.class.isInstance(ac));
System.out.println(A.class.isInstance(bc));

System.out.println();

System.out.println(B.class.isInstance(a));
System.out.println(B.class.isInstance(b));
System.out.println(B.class.isInstance(c));
System.out.println(B.class.isInstance(ac));
System.out.println(B.class.isInstance(bc));


}

}

-----------------------------------------------------------------

https://www.cnblogs.com/andy-zhou/p/5363585.html#_caption_0


快速理解Java中的五种单例模式

解法一:只适合单线程环境(不好)
package test;
/**
* @author xiaoping
*
*/
public class Singleton {
private static Singleton instance=null;
private Singleton(){

}
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}

注解:Singleton的静态属性instance中,只有instance为null的时候才创建一个实例,构造函数私有,确保每次都只创建一个,避免重复创建。
缺点:只在单线程的情况下正常运行,在多线程的情况下,就会出问题。例如:当两个线程同时运行到判断instance是否为空的if语句,并且instance确实没有创建好时,
那么两个线程都会创建一个实例。

解法二:多线程的情况可以用。(懒汉式,不好)
public class Singleton {
private static Singleton instance=null;
private Singleton(){

}
public static synchronized Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
注解:在解法一的基础上加上了同步锁,使得在多线程的情况下可以用。例如:当两个线程同时想创建实例,由于在一个时刻只有一个线程能得到同步锁,
当第一个线程加上锁以后,第二个线程只能等待。第一个线程发现实例没有创建,创建之。第一个线程释放同步锁,第二个线程才可以加上同步锁,
执行下面的代码。由于第一个线程已经创建了实例,所以第二个线程不需要创建实例。保证在多线程的环境下也只有一个实例。
缺点:每次通过getInstance方法得到singleton实例的时候都有一个试图去获取同步锁的过程。而众所周知,加锁是很耗时的。能避免则避免。

解法三:加同步锁时,前后两次判断实例是否存在(可行)
public class Singleton {
private static Singleton instance=null;
private Singleton(){

}
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}

注解:只有当instance为null时,需要获取同步锁,创建一次实例。当实例被创建,则无需试图加锁。
缺点:用双重if判断,复杂,容易出错。

解法四:饿汉式(建议使用)
public class Singleton {
private static Singleton instance=new Singleton();
private Singleton(){

}
public static Singleton getInstance(){
return instance;
}
}

注解:初试化静态的instance创建一次。如果我们在Singleton类里面写一个静态的方法不需要创建实例,它仍然会早早的创建一次实例。而降低内存的使用率。

缺点:没有lazy loading的效果,从而降低内存的使用率。

解法五:静态内部内。(建议使用)
public class Singleton {
private Singleton(){

}
private static class SingletonHolder{
private final static Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}

注解:定义一个私有的内部类,在第一次用这个嵌套类时,会创建一个实例。而类型为SingletonHolder的类,只有在Singleton.getInstance()中调用,
由于私有的属性,他人无法使用SingleHolder,不调用Singleton.getInstance()就不会创建实例。
优点:达到了lazy loading的效果,即按需创建实例。

 ----------------------------------------------

静态方法块 static 以及对象属性&类属性的用法:

静态属性是类范围里的全局变量.
静态我觉得要领悟它的2点:

1、调用的时候直接用。就是说不用实例化这个类就可以用了这个属性或者方法。
2、相当c/c++的全局变量。也就是说它保存的值就是最近一次改动它的那次。

其实两点可以归一。但是分开来更具体点。这个我在刚学的时候参考了c++里面的static,印象比较深刻。
静态属性在类没有实例化的时候就已存在,而且只能初始化一次。没必要搞的那么复杂。
静态属性,包括静态变量和静态方法直接属于该类,可以直接从类访问,不用实力该类的具体对象后再通过对象去访问
静态变量

静态变量与静态方法类似。所有此类实例共享此静态变量,也就是说在类装载时,只分配一块存储空间,所有此类的对象都可以操控此块存储空间,
当然对于final则另当别论了。看下面这段代码:

class Value{
static int c=0;
static void inc(){
c++;
}
}
class Count{
public static void prt(String s){
System.out.println(s);
}
public static void main(String[] args){
Value v1,v2;
v1=new Value();
v2=new Value();
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1.inc();
prt("v1.c="+v1.c+" v2.c="+v2.c);
}
}

结果如下:

v1.c=0 v2.c=0
v1.c=1 v2.c=1

静态方法块 static 以及对象属性&类属性的用法:
使用静态块的好处:只要在类被加载时,static块就会被调用,整个过程就调用这么一次,不会在后面的对象处又不断的调用。如果不使用它,
就会出现如下问题:new一个对象,我就要调用一次所需的这些内容,重复被调用,从而增加开销。
程序1:这个程序就是用静态方法块,测试输入一个人的出生日期,判断是否在给定出生日期范围内出生,如果是就返回true,否则返回false。
package com.liaojianya.chapter5;

import java.sql.Date;

/**
* This program will demonstrate the use of staticBlock.
* @author LIAO JIANYA
*
*/
public class StaticBlock
{
public static void main(String[] args)
{
Person1 p = new Person1(Date.valueOf("1998-11-12"));
Person1 p1 = new Person1(Date.valueOf("1988-11-12"));

System.out.println("Is this p born between 1980 and 1990:" + p.isBornBoomer());
System.out.println("Is this p1 born between 1980 and 1990:" + p1.isBornBoomer());
}

}

class Person1
{
private Date birthDate;
private static Date startDate, endDate;
static
{
startDate = Date.valueOf("1980-01-11");
endDate = Date.valueOf("1990-01-11");
}
public Person1(Date birthDate)
{
this.birthDate = birthDate;
}

boolean isBornBoomer()
{
return birthDate.compareTo(startDate) >= 0 && birthDate.compareTo(endDate) < 0;
}
}

结果显示:
Is this p born between 1980 and 1990:false
Is this p1 born between 1980 and 1990:true

TIP:先前写这个程序的时候,遇到的问题就是在Person1 p = new Person1();l

这个时候,我尝试在括号里赋日期值,报各种错误,然后才发现需要用到一个java.lang.sql里的Date.valueOf("YYYY-MM-DD")格式,而不能直接赋一个数字年份。

查了一下API如下:

public static Date valueOf(String s)

将 JDBC 日期转义形式的字符串转换成 Date 值。

参数:
  s - 表示 "yyyy-mm-dd" 形式的日期的 String 对象
返回:
  表示给定日期的 java.sql.Date 对象
抛出:
  IllegalArgumentException - 如果给定日期不是 JDBC 日期转义形式 (yyyy-mm-dd)。

package com.liaojianya.chapter1;
/**
* This program demonstrates the use of attribute of class.
* @author LIAO JIANYA
* 2016年7月20日
*/
public class UsingAttribute
{
static String a = "string-a";
static String b;

String c = "string-c";
String d;

static
{
printStatic("before static");
b = "string-b";
printStatic("after static");
}

public static void printStatic(String title)
{
System.out.println("--------" + title + "--------");
System.out.println("a = "" + a + """);
System.out.println("b = "" + b + """);
}

public UsingAttribute()
{
print("before constructor");
d = "string-d";
print("after constructor");
}

public void print(String title)
{
System.out.println("--------" + title + "--------");
System.out.println("a = "" + a + """);
System.out.println("b = "" + b + """);
System.out.println("c = "" + c + """);
System.out.println("d = "" + d + """);

}
public static void main(String[] args)
{
System.out.println();
System.out.println("------------create UsingAttribute object------------");
System.out.println();
new UsingAttribute();
System.out.println("----------------again---------------");
new UsingAttribute();
}

}

运行结果:

--------before static--------
a = "string-a"
b = "null"
--------after static--------
a = "string-a"
b = "string-b"

------------create UsingAttribute object------------

--------before constructor--------
a = "string-a"
b = "string-b"
c = "string-c"
d = "null"
--------after constructor--------
a = "string-a"
b = "string-b"
c = "string-c"
d = "string-d"
----------------again---------------
--------before constructor--------
a = "string-a"
b = "string-b"
c = "string-c"
d = "null"
--------after constructor--------
a = "string-a"
b = "string-b"
c = "string-c"
d = "string-d"

分析:

  初始化顺序:

  类属性(静态变量)定义时的初始化,如static String a = "string-a"

  static 块中的初始化代码,如static{}中的b = “string-b”

  对象属性(非静态变量)定义时的初始化, 如String c = “string-c”

  构造方法中的初始化代码,如d ="string-d"

1)static语句块用于初始化static成员变量,是最先运行的语句块,只要在类被加载时,static块就会被调用,整个过程就调用这么一次,
不会在后面的对象处又不断的调用。

2)被static修饰的变量称为类变量(class‘s variables),被类的实例所共享,某一个类的实例改变了这个静态值,其他这个类的实例也会受到影响。
而成员变量(member variables)则是没有被static修饰的变量,为实例所私有,即每个类的实例都有一份自己专属的成员变量,只有当前实例才可以改变它们的值。

 ------------------------------------------------

单例模式:

在单例模式下使用 。
getInstance(获得实例)是一个函数,是个服务类,定义一次,在java中,可以使用这种方式使用单例模式创建类的实例,所谓单例模式就是一个类有且只有一个实例,
不像object ob=new object();的这种方式去实例化后去使用。
在写程序库代码时,有时有一个类需要被所有的其它类使用,但又要求这个类只能被实例化一次,是个服务类,定义一次,其它类使用同一个这个类的实例。
例如:
class A
{
public:
A(void);
…..
}
如果在每一个需要A的类中都声明一个A类的对象,那么会导致有N个类,每个A类的定义都不一样,但是这个A类是服务类,又只能定义一次,
定义多个A类会导致A类有多个不同的内存地址。
解决这个矛盾的方法:
1. 定义一个A的全局类对象,其它类共同使用这个实例化对象,这样保证A只实例化一次,使用extern A a声明一次,在源文件中定义A a即可;
但这种方式有一个问题,就是工程之间的访问,例如pro1中有A类,pro2需要使用A类,这样就不能完全保证A类只实例化一次,可能会出现pro1和pro2各实例化一次。
2. 定义静态的实例化类(Singleton),如下:
class A
{
public:
A(void);
static A* GetInstance()
{
static A* a = NULL;
if(a == null)
{
a = new A;
};
return a;
}
……
}
这样只要包含这个头文件,
A::GetInstance()->…..
这样就保证只实例化一次。

GetInstance与new编辑对象的实例化方法,也是比较多的,最常用的方法是直接使用new,而这是最普通的,如果要考虑到其它的需要,
如单实例模式,层次间调用等等。直接使用new就不可以实现好的设计,这时候需要使用间接使用new,即很多人使用的GetInstance方法。
这是一个设计方式的代表,而不仅仅指代一个方法名。
getInstancenew的使用:
如Object _object = new Object(),这时候,就必须要知道可能会有第二个Object的存在,而第二个Object也常常是在当前的域中的,可以被直接调用的
getInstanceGetInstance的使用:
在主函数开始时调用,返回一个实例化对象。此对象是static的,在内存中保留着它的引用,即内存中有一块区域专门用来存放静态方法和变量,
可以直接使用,调用多次返回同一个对象。
getInstance两者区别对照:
大部分类(非抽象类/非接口/不屏蔽constructor的类)都可以用new,new就是通过生产一个新的实例对象,或者在栈上声明一个对象 ,
每部分的调用用的都是一个新的对象。
getInstance是少部分类才有的一个方法,各自的实现也不同。getInstance在单例模式(保证一个类仅有一个实例,并提供一个访问它的全局访问点)的类中常见,
用来生成唯一的实例,getInstance往往是static的。

单例模式:所谓单例模式就是一个类有且只有一个实例,不像object ob=new object();的这种方式去实例化后去使用。
GetInstance与new区别:
new的使用:如Object _object = new Object(),这时候,就必须要知道有第二个Object的存在,而第二个Object也常常是在当前的应用程序域中的,可以被直接调用的
GetInstance的使用:在主函数开始时调用,返回一个实例化对象,此对象是static的,在内存中保留着它的引用,即内存中有一块区域专门用来存放静态方法和变量,
可以直接使用,调用多次返回同一个对象。
两者区别对照:
大部分类(非抽象类/接口/屏蔽了constructor的类)都可以用new,new就是通过生产一个新的实例对象,或者在栈上声明一个对象 ,每部分的调用用的都是一个新的对象。
getInstance是少部分类才有的一个方法,各自的实现也不同。getInstance在单例模式(保证一个类仅有一个实例,并提供一个访问它的全局访问点)的类中常见,
用来生成唯一的实例,getInstance往往是static的。
(1)对象使用之前通过getinstance得到而不需要自己定义,用完之后不需要delete;
(2)new 一定要生成一个新对象,分配内存;getInstance() 则不一定要再次创建,它可以把一个已存在的引用给你使用,这在效能上优于new;
(3)new创建后只能当次使用,而getInstance()可以跨栈区域使用,或者远程跨区域使用。所以getInstance()通常是创建static静态实例方法的。


关于java中getInstance()方法java 先看一个例子

public abstract class TestInstance {

static int i = 1;

public static TestInstance getInstance() {

System.out.println(i++);
return null;

}
}

public class TestGetInstance {

public static void main(String[] args) {

TestInstance ins1 = TestInstance.getInstance();
TestInstance ins2 = TestInstance.getInstance();

}

}


首先声明一下的是对于抽象类,要想对其实例化,只能用getInstance方法,是不能new出来的,这个例子的运行结果是:

可以看出,i的值是改变的,这是java中的单例模式,getInstance()方法即是单例模式,是一种对于方法的引用,
相当于c++里面的指针,这从结果中是很容易看出来的,所以对于抽象方法中的调用一定要谨慎。

对象的实例化方法,也是比较多的,最常用的方法是直接使用new,而这是最普通的,如果要考虑到其它的需要,如单实例模式,层次间调用等等。
* 直接使用new就不可以实现好的设计好,这时候需要使用间接使用new,即getInstance方法。这是一个设计方式的代表,而不仅仅指代一个方法名。

* 1. new的使用:
* 如Object _object = new Object(),这时候,就必须要知道有第二个Object的存在,而第二个Object也常常是在当前的应用程序域中的,
* 可以被直接调用的
*
* 2. GetInstance的使用:
* 在主函数开始时调用,返回一个实例化对象,此对象是static的,在内存中保留着它的引用,即内存中有一块区域专门用来存放静态方法和变量,
* 可以直接使用,调用多次返回同一个对象。
*
* 3.两者区别对照:
* 大部分类(非抽象类/接口/屏蔽了constructor的类)都可以用new,new就是通过生产一个新的实例对象,或者在栈上声明一个对象 ,每部分的调用
* 用的都是一个新的对象。
*
* getInstance是少部分类才有的一个方法,各自的实现也不同。
* getInstance在单例模式(保证一个类仅有一个实例,并提供一个访问它的全局访问点)的类中常见,用来生成唯一的实例,getInstance往往是static的。
*
* (1) 对象使用之前通过getInstance得到而不需要自己定义,用完之后不需要delete;
* (2)new 一定要生成一个新对象,分配内存;getInstance() 则不一定要再次创建,它可以把一个已存在的引用给你使用,这在效能上优于new;
* (3) new创建后只能当次使用,而getInstance()可以跨栈区域使用,或者远程跨区域使用。所以getInstance()通常是创建static静态实例方法的。
*
* 总结:
* getInstance这个方法在单例模式用的甚多,为了避免对内存造成浪费,直到需要实例化该类的时候才将其实例化,所以用getInstance来获取该对象,
* 至于其他时候,也就是为了简便而已,为了不让程序在实例化对象的时候,不用每次都用new关键字,索性提供一个instance方法,不必一执行这个类就
* 初始化,这样做到不浪费系统资源!
*
* 单例模式 可以防止 数据的冲突,节省内存空间
*
*/
01.//使用实例,在定义的新类当中加入getInstance()方法,返回值即为该类的一个对象,此方法常常应用在Java的单例模式当中
02.public class OAuthConstant {
03.
04. public static synchronized OAuthConstant getInstance(){
05. if(instance == null)
06. instance = new OAuthConstant();
07. return instance;
08. }
09.}
10.
11.//主函数当中使用此类的getInstance()函数,即可得到系统当前已经实例化的该类对象,若当前系统还没有实例化过这个类的对象,则调用此类的构造函数
12.//实例化一个对象,并返回
13.OAuthConstant.getInstance();

-----------------------------------

rownum用法:

rownum的用法:
ORACLE 中ROWNUM用法总结!
对于 Oracle 的 rownum 问题,很多资料都说不支持>,>=,=,between...and,只能用以上符号(<、<=、!=),并非说用>,& gt;=,=,between..and 时会提示SQL语法错误,而是经常是查不出一条记录来,还会出现似乎是莫名其妙的结果来,其实您只要理解好了这个 rownum 伪列的意义就不应该感到惊奇,同样是伪列,rownum 与 rowid 可有些不一样,下面以例子说明

假设某个表 t1(c1) 有 20 条记录

如果用 select rownum,c1 from t1 where rownum < 10, 只要是用小于号,查出来的结果很容易地与一般理解在概念上能达成一致,应该不会有任何疑问的。

可如果用 select rownum,c1 from t1 where rownum > 10 (如果写下这样的查询语句,这时候在您的头脑中应该是想得到表中后面10条记录),你就会发现,显示出来的结果要让您失望了,也许您还会怀疑是不谁删了一些记录,然后查看记录数,仍然是 20 条啊?那问题是出在哪呢?

先好好理解 rownum 的意义吧。因为ROWNUM是对结果集加的一个伪列,即先查到结果集之后再加上去的一个列 (强调:先要有结果集)。简单的说 rownum 是对符合条件结果的序列号。它总是从1开始排起的。所以你选出的结果不可能没有1,而有其他大于1的值。所以您没办法期望得到下面的结果集:

11 aaaaaaaa
12 bbbbbbb
13 ccccccc
.................

rownum >10 没有记录,因为第一条不满足去掉的话,第二条的ROWNUM又成了1,所以永远没有满足条件的记录。或者可以这样理解:

ROWNUM是一个序列,是oracle数据库从数据文件或缓冲区中读取数据的顺序。它取得第一条记录则rownum值为1,第二条为2,依次类推。如果你用>,>=,=,between...and这些条件,因为从缓冲区或数据文件中得到的第一条记录的rownum为1,则被删除,接着取下条,可是它的rownum还是1,又被删除,依次类推,便没有了数据。

有了以上从不同方面建立起来的对 rownum 的概念,那我们可以来认识使用 rownum 的几种现像

1. select rownum,c1 from t1 where rownum != 10 为何是返回前9条数据呢?它与 select rownum,c1 from tablename where rownum < 10 返回的结果集是一样的呢?
因为是在查询到结果集后,显示完第 9 条记录后,之后的记录也都是 != 10,或者 >=10,所以只显示前面9条记录。也可以这样理解,rownum 为9后的记录的 rownum为10,因条件为 !=10,所以去掉,其后记录补上,rownum又是10,也去掉,如果下去也就只会显示前面9条记录了

2. 为什么 rownum >1 时查不到一条记录,而 rownum >0 或 rownum >=1 却总显示所以的记录
因为 rownum 是在查询到的结果集后加上去的,它总是从1开始

3. 为什么 between 1 and 10 或者 between 0 and 10 能查到结果,而用 between 2 and 10 却得不到结果
原因同上一样,因为 rownum 总是从 1 开始

从上可以看出,任何时候想把 rownum = 1 这条记录抛弃是不对的,它在结果集中是不可或缺的,少了rownum=1 就像空中楼阁一般不能存在,所以你的 rownum 条件要包含到 1

但如果就是想要用 rownum > 10 这种条件的话话就要用嵌套语句,把 rownum 先生成,然后对他进行查询。
select *
from (selet rownum as rn,t1.* from a where ...)
where rn >10

一般代码中对结果集进行分页就是这么干的。

另外:rowid 与 rownum 虽都被称为伪列,但它们的存在方式是不一样的,rowid 可以说是物理存在的,表示记录在表空间中的唯一位置ID,在DB中唯一。只要记录没被搬动过,rowid是不变的。rowid 相对于表来说又像表中的一般列,所以以 rowid 为条件就不会有 rownum那些情况发生。
另外还要注意:rownum不能以任何基表的名称作为前缀。


下面是关于rownum的介绍
Rownum和row_number() over()的使用
ROWNUM是Oracle从8开始提供的一个伪列,是把SQL出来的结果进行编号,始终从1开始,常见的用途就是用来分页输出.

比如
SELECT *
FROM torderdetail a
WHERE ROWNUM <= 10

这条语句就是输出前10条纪录,在这里用途上类似于sql sever的top,不过rownum对于指定编号区间的输出应该说更强大

SELECT *
FROM (SELECT a.*, ROWNUM rn
FROM torderdetail a)
WHERE rn >= 10 AND rn <= 20
这条语句即是输出Oracle查询第10到第20条纪录,这里之所以用rownum rn,是把rownum转成实例,因为rownum本身只能用 <=的比较方式,只有转成实列,这样就可做 >=的比较了。
在实际用途中,常常会要求取最近的几条纪录,这就需要先对纪录进行排序后再取rownum <=

一般常见的
SELECT *
FROM (SELECT a.*
FROM torderdetail a
ORDER BY order_date DESC)
WHERE ROWNUM <= 10 而在CSDN曾经发生过讨论,关于取近的10条纪录,有人给出这样的语句

SELECT a.*
FROM torderdetail a
WHERE ROWNUM <= 10
ORDER BY order_date DESC 之所以会出现这样的语句,主要是从效率上的考虑,前面条语句,是要进行全表扫描后再排序,然后再取10条纪录,后一条语句则不会全表扫描,只会取出10条纪录,很明显后条语句的效率会高许多。
那为什么会有争议呢,那就在于在执行顺序上争议,是先执行排序取10条纪录,还是取10条纪录,再排序呢?两种顺序取出来的结果是截然相反的,Oracle查询前10条记录时先排序再取10条,就是取最近的10条,而先取10条,再排序,则取出的最早的10条纪录。对于此语句,普遍的认为执行顺序是先取10条纪录再排序的。
所以此语句应该是错误。但实际上并非如此,此语句的执行顺序和order by的字段有关系,如果你order by 的字段是pk,则是先排序,再取10条(速度比第一种语句快),而排序字段不是PK 时,是先取10条再排序,此时结果就与要求不一样了,所以第二种写法一定要在排序字段是主键的情况下才能保证结果正确。
Row_number() over()这个分析函数是从9I开始提供的,一般的用途和rownum差不多。
一般写法row_number() over( order by order_date desc) 生成的顺序和rownum的语句一样,效率也一样(对于同样有order by 的rownum语句来说),所以在这种情况下两种用法是一样的。
而对于分组后取最近的10条纪录,则是rownum无法实现的,这时只有row_number可以实现,row_number() over(partition by 分组字段 order by 排序字段)就能实现分组后编号,比如说要取近一个月的每天最后10个订单纪录

SELECT *
FROM (SELECT a.*,
ROW_NUMBER () OVER (PARTITION BY TRUNC (order_date) ORDER BY order_date DESC)
rn
FROM torderdetail a)
WHERE rn <= 10 Rownum的另类用法,有时候我们会遇到这种需求,要求输出当月的所有天数,许多人会烦恼,数据库里又没有这样的表,怎么输出一个月的所有天数呢?用rownum就能解决:


SELECT TRUNC (SYSDATE, 'MM') + ROWNUM - 1
FROM DUAL
CONNECT BY ROWNUM <= TO_NUMBER
(TO_CHAR (LAST_DAY (SYSDATE), 'dd')) 以上的相关内容就是对Oracle查询前10条记录的介绍。


综上所述:oracle查询第5条到第10记录分页查询为:

select * from (select a.*,rownum rn from (select * from scott.emp) a where rownum<=10) where rn>=5;


二、
oracle查询,要求查出来前5条和后5条数据,并且让他们重复3次??
with t as
(select row_number() over (order by id) rn,表名.* from 表名)
select * from t where (rn between 1 and 5) or (rn between (select max(rn)-4 from t) and (select max(rn) from t))
union all
select * from t where (rn between 1 and 5) or (rn between (select max(rn)-4 from t) and (select max(rn) from t))
union all
select * from t where (rn between 1 and 5) or (rn between (select max(rn)-4 from t) and (select max(rn) from t))

row_number这个东西很强大基本是用来排名的,比如我上边的那个用法 也可以分组排名row_number() over (partition by 分组字段 order by 排名字段)
而rownum只是一个表各条数据的行号,order by 什么以后行号不会变的

三、
Oralce的示例:

1. 最佳选择:利用分析函数

row_number() over ( partition by col1 order by col2 )
比如想取出100-150条记录,按照tname排序

select tname,tabtype from (
select tname,tabtype,row_number() over ( order by tname ) rn from tab
) where rn between 100 and 150;

2. 使用rownum 虚列

select tname,tabtype from (
select tname,tabtype,rownum rn from tab where rownum <= 150
) where rn >= 100;

注释:使用虚列时不能基于整个记录集合来进行排序,假如指定了order by子句,排序的是选出来的记录集的排序 create table mynumber(id int,name varchar(10));
insert into mynumber values(1,'no1');
insert into mynumber values(2,'no2');
insert into mynumber values(3,'no3');
insert into mynumber values(4,'no4');
insert into mynumber values(5,'no5');
insert into mynumber values(5,'no6');
insert into mynumber values(6,'no7');
insert into mynumber values(7,'no8');
insert into mynumber values(8,'no9');
insert into mynumber values(9,'no10');
insert into mynumber values(9,'no11');
insert into mynumber values(9,'no12');
insert into mynumber values(10,'no13');
insert into mynumber values(10,'no14');
insert into mynumber values(10,'no15');
insert into mynumber values(11,'no16');
insert into mynumber values(12,'no17');
insert into mynumber values(13,'no18');


select id,name,RANK() over ( order by id ) case1,
DENSE_RANK() over ( order by id ) case2,
row_number() over ( order by id ) case3 from mynumber;

(1) 取前10条不同id记录,假如最后1条记录的ID依然有相同的,那么取出来

select id,name from mynumber where id in
(select id from (select distinct id
from mynumber) tt where rownum<=10);

select * from (select id,name,RANK()
over ( order by id ) case1,DENSE_RANK()
over ( order by id ) case2,row_number()
over ( order by id ) case3 from mynumber)
tt where case1<=10;
select * from (select id,name,RANK() over
( order by id ) case1,DENSE_RANK() over
( order by id ) case2,row_number() over
( order by id ) case3 from mynumber)
tt where case1 between 5 and 10;

(2)取前10条记录,假如第10条记录的ID 还有相同的,那么取出来

select * from mynumber where id in
(select id from mynumber where rownum <=10);

select * from (select id,name,RANK()
over ( order by id ) case1,DENSE_RANK()
over ( order by id ) case2,row_number()
over ( order by id ) case3 from mynumber)
tt where case2<=10;
select * from (select id,name,RANK()
over ( order by id ) case1,DENSE_RANK()
over ( order by id ) case2,row_number()
over ( order by id ) case3 from mynumber)
tt where case2 between 5 and 10;

(3)取前10条记录

select id,name from mynumber
where rownum <=10;
select id,name from
(select id,name,rownum rn from
mynumber where rownum <= 10 ) where rn >= 5;

select * from (select id,name,RANK()
over ( order by id ) case1,DENSE_RANK()
over ( order by id ) case2,row_number()
over ( order by id ) case3 from mynumber)
tt where case3<=10;
select * from (select id,name,RANK()
over ( order by id ) case1,DENSE_RANK()
over ( order by id ) case2,row_number()
over ( order by id ) case3 from mynumber)
tt where case3 between 5 and 10;

------------------------------------------

merge into的用法


******视图*********
Oracle对象教程:视图(View)创建使用,视图(View)实际上是一张或者多张表上的预定义查询,这些表称为基表。从视图中查询信息与从表中查询信息的方法完全相同。
只需要简单的SELECT…FROM即可。

视图具有以下优点:
1. 可以限制用户只能通过视图检索数据。这样就可以对最终用户屏蔽建表时底层的基表。
2. 可以将复杂的查询保存为视图。可以对最终用户屏蔽一定的复杂性。
3. 限制某个视图只能访问基表中的部分列或者部分行的特定数据。这样可以实现一定的安全性。
4. 从多张基表中按一定的业务逻辑抽出用户关心的部分,形成一张虚拟表

创建语法:
CREATE [OR REPLACE] [{FORCE|NOFORCE}] VIEW view_name AS SELECT查询 [WITH READ ONLY CONSTRAINT]

语法解析:
1. OR REPLACE:如果视图已经存在,则替换旧视图。
2. FORCE:即使基表不存在,也可以创建该视图,但是该视图不能正常使用,当基表创建成功后,视图才能正常使用。
3. NOFORCE:如果基表不存在,无法创建视图,该项是默认选项。
4. WITH READ ONLY:默认可以通过视图对基表执行增删改操作,但是有很多在基表上的限制(比如:基表中某列不能为空,但是该列没有出现在视图中,
则不能通过视图执行insert操作),WITH READ ONLY说明视图是只读视图,不能通过该视图进行增删改操作。现实开发中,基本上不通过视图对表中的数据进行增删改操作。

案例3:基于EMP表和DEPT表创建视图
SQL> CREATE OR REPLACE VIEW EMPDETAIL
AS SELECT EMPNO,ENAME,JOB,HIREDATE,EMP.DEPTNO,DNAME
FROM EMP JOIN DEPT ON EMP.DEPTNO=DEPT.DEPTNO
WITH READ ONLY
/
代码解析:
① 对视图可以像表一样进行查询。该视图中隐藏了员工的工资。
删除视图可以使用“DROP VIEW 视图名称”,删除视图不会影响基表的数据。


*********Oracle左连接、右连接、全外连接以及(+)号用法*********
Oracle 表之间的连接分为三种:
1. 内连接(自然连接)
2. 外连接
(1)左外连接 (左边的表不加限制)
(2)右外连接(右边的表不加限制)
(3)全外连接(左右两表都不加限制)
3. 自连接(同一张表内的连接
SQL的标准语法:
select table1.column,table2.column
from table1 [inner | left | right | full ] join table2 on table1.column1 = table2.column2;
inner join 表示内连接;
left join表示左外连接;
right join表示右外连接;
full join表示完全外连接;
on子句 用于指定连接条件。


注意:

如果使用from子句指定内、外连接,则必须要使用on子句指定连接条件;
如果使用(+)操作符指定外连接,则必须使用where子句指定连接条件。


Oracle 外连接(OUTER JOIN)包括以下:
•左外连接(左边的表不加限制)
•右外连接(右边的表不加限制)
•全外连接(左右两表都不加限制)
对应SQL:LEFT/RIGHT/FULL OUTER JOIN。 通常省略OUTER关键字, 写成:LEFT/RIGHT/FULL JOIN。
在左连接和右连接时都会以一张A表为基础表,该表的内容会全部显示,然后加上A表和B表匹配的内容。
如果A表的数据在B表中没有记录。 那么在相关联的结果集行中列显示为空值(NULL)。
对于外连接, 也可以使用“(+) ”来表示。 关于使用(+)的一些注意事项:
1.(+)操作符只能出现在WHERE子句中,并且不能与OUTER JOIN语法同时使用。
2. 当使用(+)操作符执行外连接时,如果在WHERE子句中包含有多个条件,则必须在所有条件中都包含(+)操作符。
3.(+)操作符只适用于列,而不能用在表达式上。
4.(+)操作符不能与OR和IN操作符一起使用。
5.(+)操作符只能用于实现左外连接和右外连接,而不能用于实现完全外连接。


演示代码:
REATE TABLE t_A (
id number,
name VARCHAR2(10)
);

CREATE TABLE t_B (
id number,
name VARCHAR2(10)
);

INSERT INTO t_A VALUES(1,'A');
INSERT INTO t_A VALUES(2,'B');
INSERT INTO t_A VALUES(3,'C');
INSERT INTO t_A VALUES(4,'D');
INSERT INTO t_A VALUES(5,'E');

INSERT INTO t_B VALUES(1,'AA');
INSERT INTO t_B VALUES(1,'BB');
INSERT INTO t_B VALUES(2,'CC');
INSERT INTO t_B VALUES(1,'DD');

左外连接(left outer join/left join)
LEFT JOIN是以左表的记录为基础的,示例中t_A可以看成左表,t_B可以看成右表,它的结果集是t_A表中的全部数据,再加上t_A表和t_B表匹配后的数据。
换句话说,左表(t_A)的记录将会全部表示出来,而右表(t_B)只会显示符合搜索条件的记录。t_B表记录不足的地方均为NULL。
select * from t_A a left join t_B b on a.id = b.id;

select * from t_A a left outer join t_B b on a.id = b.id;
用(+)来实现, 这个+号可以这样来理解: + 表示补充,即哪个表有加号,这个表就是匹配表。如果加号写在右表,左表就是全部显示,所以是左连接。
Select * from t_A a,t_B b where a.id=b.id(+);

左外连接(right outer join/right join)
和LEFT JOIN的结果刚好相反,是以右表(t_B)为基础的。它的结果集是t_B表所有记录,再加上t_A和t_B匹配后的数据。 t_A表记录不足的地方均为NULL。
select * from t_A a right join t_B b on a.id = b.id;

select * from t_A a right outer join t_B b on a.id = b.id;
用(+)来实现, 这个+号可以这样来理解: + 表示补充,即哪个表有加号,这个表就是匹配表。如果加号写在左表,右表就是全部显示,所以是右连接。
Select * from t_A a,t_B b where a.id(+)=b.id;

全连接(full outer join/full join)
左表和右表都不做限制,所有的记录都显示,两表不足的地方均为NULL。 全外连接不支持(+)写法。
select * from t_A a full join t_B b on a.id = b.id;

select * from t_A a full outer join t_B b on a.id = b.id;

补充
select * from t_A a,t_B b where a.id = b.id;
select * from t_A a join t_B b on a.id = b.id;


select * from t_A a where a.id in (select b.id from t_B b);
select * from t_A a where exists (select 1 from t_B b where a.id = b.id);

多表连接操作
在进行多表联合查找时,会发现多表会进行连接操作的,而这些连接操作包括三种方式:

Hash Join(散列连接)、Nested Loops、Sort Merge join,对于这些连接方式的了解可以方便我们对于连接操作的进一步了解,下面进行一一介绍。

3.1 HASH JOIN(散列连接)
Hash Join散列连接主要是CBO(CBO: Cost-Based Optimization 基于代价的优化器, Oracle优化器之一,后续会进行介绍)做数据量比较大时进行连接操作比较常用的一种方式,优化器会选用两个表中较小那个表(小一点表或者数据源),利用连接键(JOIN KEY)在内存中建立散列表,将列数据存储到hash列表中,然后扫描大的那个表,同样对JOIN KEY到hash表进行匹配,找出可以匹配的值,此时注意:如果HASH表比较大,无法一次存储到内存时则会分成不多个partition(段),写入磁盘的temporary segment,此时性能会多出一次写的代价,有可能会降低效率。

该内容主要适用于较小的表(可以放入内存),此时相关效能就是访问了两个的性能的成本总和。

可以用USE_HASH(table_name1 table_name2)提示来强制使用散列连接。

3.2 SORT MERGE JOIN:排序合并连接
Merge Join排序合并连接,是先将两个关联的表按照关联键(JOIN KEY)进行排序,然后从各自排序表中抽取数据,到另一个排序表中进行匹配。

相对来说,merge join需要完成排序操作,所以消耗的性能比较多,但是当源如果已经进行了排序,其将会取得较好的性能。适用于:不等价关联(>,<,>=,<=,<>)、HASH_JOIN_ENABLED=false等情况。

可以使用USE_MERGE(table_name1 table_name2)来强制使用排序合并连接.

3.3 NESTED LOOP:嵌套循环连接
Nested Loops嵌套循环连接,工作方式是循环从一张表中读取数据(驱动表 outer table),然后访问另一张表(被查找表 inner table, 希望有索引)。驱动表中每一行与inner表中相应记录进行链接(JOIN)。内表被外表驱动,外表中的每一行都会与内表进行匹配操作,所以查询结果集最好不要太大。将数据量小的表作为查询的驱动表(外表),可以利用ordered 来提示CBO默认的驱动表。

对于驱动表较小的情况时,嵌套循环连接相对比较好,同时inner表需要有效的访问索引(index)。

使用USE_NL(table_name1 table_name2)可是强制CBO 执行嵌套循环连接。

****************oracle中的exists 和not exists 用法详解*******************
有两个简单例子,以说明 “exists”和“in”的效率问题

1) select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ;

T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高。

2) select * from T1 where T1.a in (select T2.a from T2) ;
T1数据量非常大而T2数据量小时,T1>>T2 时,2) 的查询效率高。

exists 用法:
请注意 1)句中的有颜色字体的部分 ,理解其含义;
其中 “select 1 from T2 where T1.a=T2.a” 相当于一个关联表查询,相当于

“select 1 from T1,T2 where T1.a=T2.a”

但是,如果你当当执行 1) 句括号里的语句,是会报语法错误的,这也是使用exists需要注意的地方。

“exists(xxx)”就表示括号里的语句能不能查出记录,它要查的记录是否存在。

因此“select 1”这里的 “1”其实是无关紧要的,换成“*”也没问题,它只在乎括号里的数据能不能查找出来,是否存在这样的记录,如果存在,这 1)句的where 条件成立。


in 的用法:
继续引用上面的例子
“2) select * from T1 where T1.a in (select T2.a from T2) ”
这里的“in”后面括号里的语句搜索出来的字段的内容一定要相对应,一般来说,T1和T2这两个表的a字段表达的意义应该是一样的,否则这样查没什么意义。
打个比方:T1,T2表都有一个字段,表示工单号,但是T1表示工单号的字段名叫“ticketid”,T2则为“id”,但是其表达的意义是一样的,而且数据格式也是一样的。
这时,用 2)的写法就可以这样:

“select * from T1 where T1.ticketid in (select T2.id from T2) ”

Select name from employee where name not in (select name from student);

Select name from employee where not exists (select name from student);

第一句SQL语句的执行效率不如第二句。
通过使用EXISTS,Oracle会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。Oracle在执行IN子查询时,首先执行子查询,
并将获得的结果列表存放在一个加了索引的临时表中。在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。
这也就是使用EXISTS比使用IN通常查询速度快的原因

 ----------------------------

java中子类继承父类时是否继承构造函数:

隐式的超级构造函数FatherClass()是未定义的。必须显式地调用另一个构造函数
Implicit super constructor FatherClass() is undefined. Must explicitly invoke another constructor

Constructor call must be the first statement in a constructor
构造函数调用必须首先声明一个构造函数

The public type aa must be defined in its own file

java继承中对构造函数是不继承的,只是调用(隐式或显式)。

以下是例子:

public class FatherClass {

public FatherClass() {
System.out.println(100);
}

public FatherClass(int age) {
System.out.println(age);
}

}

public class SonClass extends FatherClass{

public SonClass() {
}

public SonClass(int c) {
System.out.println(1234);
}

public static void main(String[] args) {

SonClass s = new SonClass(66);

}
}

编译后执行结果如下是什么呢?

分析:SonClass s = new SonClass(66);执行这句时,调用

public SonClass(int c) {
System.out.println(1234);//系统会自动先调用父类的无参构造函数(super())
}

在这个构造函数中,等价于

public SonClass(int c) {

super();//必须是第1行,否则不能编译
System.out.println(1234);
}

所以结果是 100
1234

在创建子类的对象时,Java虚拟机首先执行父类的构造方法,然后再执行子类的构造方法。在多级继承的情况下,将从继承树的最上层的父类开始,依次执行各个类的构造方法,
这可以保证子类对象从所有直接或间接父类中继承的实例变量都被正确地初始化。

3.如果子类构造函数是这样写的

public SonClass(int c) {

super(22);//必须是第1行,否则不能编译
//显式调用了super后,系统就不再调用无参的super()了;
System.out.println(1234);
}

执行结果是 22
1234

总结1:构造函数不能继承,只是调用而已。

如果父类没有无参构造函数

创建子类时,不能编译,除非在构造函数代码体中第一行,必须是第一行显式调用父类有参构造函数

如下:

SonClass (){

super(777);//显示调用父类有参构造函数

System.out.println(66);

}

如果不显示调用父类有参构造函数,系统会默认调用父类无参构造函数super();

但是父类中没有无参构造函数,那它不是不能调用了。所以编译就无法通过了。

总结2:创建有参构造函数后,系统就不再有默认无参构造函数。

如果没有任何构造函数,系统会默认有一个无参构造函数。

 ---------------------------------------

Java中单例模式和静态类的区别:

Java中单例模式和静态类的区别:
单例模式与静态类(一个类,所有方法为静态方法)是另一个非常有趣的问题,在《Java中有关单例模式的面试问题》博文中露掉了,由于单例模式和静态类都具有良好的
访问性,它们之间有许多相似之处,例如,两者可以直接使用而无须创建对象,都可提交唯一实例,在一个非常高的高度上看起来它们都为是用于同样的任务。
由于它们具有较多的相似性,面试官常常会问一些类似为神马使用单例模式替换静态方法?你能使用静态类替换单例模式吗?Java中单例模式与静态的区别有那些?
等这样的问题,为回答这些问题,记住他们单例模式和静态方法之间基本的区别是非常重要的,前者给你一个Object,后者仅仅提供静态方法,
由于对像比方法具有较强的能力,可以指导你神马时候使用单例模式与静态方法。


在本文中,我们会了解神马Java中的神马地方使用单例模式,神马时候使用静态类更好,顺便说下,JDK中有几个关于两者的例子,并且这例子非常聪明的,
例如java.lang.Math是一个final类,并且其方法为静态方法,另一方面java.lang.Runtime是一个单例的类。对于那些不熟悉单例模式或静态类的人,
静态类就是一个Java类,它仅包含静态方法,一个非常好静态类的例子就是java.lang.Math,它包括了许多为不同数据功能实现工具方法,例如sqrt(),
而单例类,在整个应用生命周期内只有一个实例,例如java.lang.Runtime。

神马时候在Java中使用静态类替换单例
确实存在一些场景,静态类比单例更适合,这个场景中主要的一个例子就是java.lang.Math,它不是单例的,其所有方法都是静态方法,这里我给出几个场景,
我觉得使用静态类比单例模式更适合。
1)如果你的单例不需要维护任何状态,仅仅提供全局访问的方法,这种情况考虑使用静态类,静态方法比单例更快,因为静态的绑定是在编译期就进行的。
但是要记住,不建议在静态类中维护状态信息,特别是在并发环境中,若无适当的同步措施而修改多线程并发时,会导致坏的竞态条件。
如果你需要将一些工具方法集中在一起时,你可以选择使用静态方法,但是别的东西,要求单例访问资源时,应该使用单例模式。

Java中单例与静态的区别
这是回答关于单例与静态的第二面试问题,如我早些提到过的,它们基本的区别一个表现类,一个表现方法,下面列几条它们之间的区别。
1)静态类比单例具有更好的性能,因为静态方法在编译期绑定。
2)再次,它们的区别是override的能力,因Java中的静态方法是不可以覆盖的,这就导致其木有太多的灵活性,另一面,你可通过继承的方式覆盖单例类中定义的方法。
3)静态类很难模拟,因此难于单例测试,单例更容易模拟,因为也比静态类易于编写单元测试,不论神马单例期望神马,你都可以传递模拟对象,例如构造方法或方法参数。
4)如果你的需求中需要维护状态信息,则单例比静态类更适合,因为后者在维护状态信息方面是非常可怕的,并导致狡滑的bug。
5)如果是一个非常重的对象,单例可以懒加载,但是静态类没有这样的优势,并且非常热切的加载。
6)许多依赖注入的框架对单例都有良好的管理,例如Spring,使用它们非常容易。
两者之间的这些区别,有助于我们在面对一些场景时做出选择,下一节中了解神马时候选择单例而不是静态类。
Java中,选择单例而不是静态类的优点
单例与静态主要的优点是前者比后者更具有面向对象的能力,使用单例,可以通过继承和多态扩展基类,实现接口和更有能力提供不同的实现,
如果我们讨论java.lang.Runtime,在Java中它是单例,调用getRuntime()方法,会基于不同的JVM返回不同的实现,但也保证了每个JVM中实有一个实例,
如果java.lang.Runtime是一个静态类,不太可能因不同的JVM返回不同的实现。

这就是Java中单例与静态类的区别,当你需要一个全OO能力的对象时,选择单例,如果仅仅是将一些静态方法预售,使用静态类。

---------------------------------

Java对象及其引用:

Java对象及其引用
关于对象与引用之间的一些基本概念。

初学Java时,在很长一段时间里,总觉得基本概念很模糊。后来才知道,在许多Java书中,把对象和对象的引用混为一谈。可是,如果我分不清对象与对象引用,

那实在没法很好地理解下面的面向对象技术。把自己的一点认识写下来,或许能让初学Java的朋友们少走一点弯路。

为便于说明,我们先定义一个简单的类:

class Vehicle {

int passengers;

int fuelcap;

int mpg;

}

有了这个模板,就可以用它来创建对象:

Vehicle veh1 = new Vehicle();

通常把这条语句的动作称之为创建一个对象,其实,它包含了四个动作。

1)右边的“new Vehicle”,是以Vehicle类为模板,在堆空间里创建一个Vehicle类对象(也简称为Vehicle对象)。

2)末尾的()意味着,在对象创建后,立即调用Vehicle类的构造函数,对刚生成的对象进行初始化。构造函数是肯定有的。如果你没写,Java会给你补上一个默认的构造函数。

3)左边的“Vehicle veh 1”创建了一个Vehicle类引用变量。所谓Vehicle类引用,就是以后可以用来指向Vehicle对象的对象引用。

4)“=”操作符使对象引用指向刚创建的那个Vehicle对象。

我们可以把这条语句拆成两部分:

Vehicle veh1;

veh1 = new Vehicle();

效果是一样的。这样写,就比较清楚了,有两个实体:一是对象引用变量,一是对象本身。

在堆空间里创建的实体,与在数据段以及栈空间里创建的实体不同。尽管它们也是确确实实存在的实体,但是,我们看不见,也摸不着。不仅如此,

我们仔细研究一下第二句,找找刚创建的对象叫什么名字?有人说,它叫“Vehicle”。不对,“Vehicle”是类(对象的创建模板)的名字。

一个Vehicle类可以据此创建出无数个对象,这些对象不可能全叫“Vehicle”。

对象连名都没有,没法直接访问它。我们只能通过对象引用来间接访问对象。

为了形象地说明对象、引用及它们之间的关系,可以做一个或许不很妥当的比喻。对象好比是一只很大的气球,大到我们抓不住它。引用变量是一根绳, 可以用来系汽球。

如果只执行了第一条语句,还没执行第二条,此时创建的引用变量veh1还没指向任何一个对象,它的值是null。引用变量可以指向某个对象,或者为null。

它是一根绳,一根还没有系上任何一个汽球的绳。执行了第二句后,一只新汽球做出来了,并被系在veh1这根绳上。我们抓住这根绳,就等于抓住了那只汽球。

再来一句:

Vehicle veh2;

就又做了一根绳,还没系上汽球。如果再加一句:

veh2 = veh1;

系上了。这里,发生了复制行为。但是,要说明的是,对象本身并没有被复制,被复制的只是对象引用。结果是,veh2也指向了veh1所指向的对象。两根绳系的是同一只汽球。

如果用下句再创建一个对象:

veh2 = new Vehicle();

则引用变量veh2改指向第二个对象。

从以上叙述再推演下去,我们可以获得以下结论:

(1)一个对象引用可以指向0个或1个对象(一根绳子可以不系汽球,也可以系一个汽球);

(2)一个对象可以有N个引用指向它(可以有N条绳子系住一个汽球)。

如果再来下面语句:

veh1 = veh2;

按上面的推断,veh1也指向了第二个对象。这个没问题。问题是第一个对象呢?没有一条绳子系住它,它飞了。多数书里说,它被Java的垃圾回收机制回收了。

这不确切。正确地说,它已成为垃圾回收机制的处理对象。至于什么时候真正被回收,那要看垃圾回收机制的心情了。

由此看来,下面的语句应该不合法吧?至少是没用的吧?

new Vehicle();

不对。它是合法的,而且可用的。譬如,如果我们仅仅为了打印而生成一个对象,就不需要用引用变量来系住它。最常见的就是打印字符串:

System.out.println(“I am Java!”);

字符串对象“I am Java!”在打印后即被丢弃。有人把这种对象称之为临时对象。

对象与引用的关系将持续到对象回收

Java在运行时才处理别名引用

原文地址:https://www.cnblogs.com/wjy123/p/8577908.html