一 .公有继承(public) n 基类的public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可访问。 n 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。 n 通过派生类的对象只能访问基类的public成员 二.私有继承 n 基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可访问。 n 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。 n 通过派生类的对象不能访问基类中的任何成员。 三.保护继承(protected) n 基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可访问。 n 派生类中的成员函数可以直接访问基类中的public和protected成员,但不能访问基类的private成员。 n 通过派生类的对象不能访问基类中的任何成员 protected 成员的特点与作用 n 对建立其所在类对象的模块来说(水平访问时),它与 private 成员的性质相同。 n 对于其派生类来说(垂直访问时),它与 public 成员的性质相同。 n 既实现了数据隐藏,又方便继承,实现代码重用 四.函数与类的根本差别是: n 函数是将逻辑上相关的语句与数据封装,用于完成特定的功能。 n 而类则是逻辑上相关的函数与数据的封装,它是对所要处理的问题的描述 五.使用static注意: n 类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致了它仅能访问类的静态数据和静态成员函数。 n 静态数据成员是静态存储的,所以必须对它进行初始化。 (与全局对象一样对于静态数据成员在程序中也只能提供一个定义,故静态数据成员的初始化不应该被放在头文件中而应该放在含有类的非inline 函数定义的文件中) 六.拷贝构造函数 n 作用:使用一个对象(参数指定的对象),去初始化一个正在被建立的同类型对象 n 类名(类名 &对象名);//拷贝构造函数 n 这个拷贝构造函数执行的功能是:用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员。 n 关于拷贝构造函数在以下三种情况下会被自动使用: n (1)当用类的一个对象去初始化该类的另一个对象时系统自动调用拷贝构造函数实现拷贝赋值。 n void main(void) n { Point A(1,2); n Point B(A); //拷贝构造函数被调用 n cout<<B.GetX()<<endl; n } n (2)若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数。例如: n void fun1(Point p) n { cout<<p.GetX( )<<endl; n } n void main( ) n { Point A(1,2); n fun1(A); //调用拷贝构造函数 n } n (3)当函数的返回值是类对象时,系统自动调用拷贝构造函数。例如: n Point fun2() n { Point A(1,2); n return A; //调用拷贝构造函数 n } n int main() n { n Point B; n B=fun2(); n } 七.方法的重写要遵循“两同两小一大”的原则 1>两同即:方法名相同,形参列表相同 2> 两小即:子类方法的返回类型应该比父类的方法的返回类型更小或相同,子类声明抛出的异常应比父类方法声明抛出的异常更小或相同; 3>一大即:子类方法的访问权限比父类方法更大或相等 八.内部类 一.内部类的分类 成员内部类 局部内部类 静态内部类 1.1.1.成员内部类 作为外部类的一个成员存在,与外部类的属性、方法并列。 内部类和外部类的实例变量可以共存。 在内部类中访问实例变量:this.属性 在内部类访问外部类的实例变量:外部类名.this.属性。 在外部类的外部访问内部类,使用out.inner. 成员内部类的特点: 1.内部类作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为PRIVATE,但是对于处于其内部的内部类还是可见的。) 2.用内部类定义在外部类中不可访问的属性。这样就在外部类中实现了比外部类的private还要小的访问权限。 注意:内部类是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。 对于一个名为outer的外部类和其内部定义的名为inner的内部类。编译完成后出现outer.class和outer$inner.class两类。 3.成员内部类不能有静态属性 建立内部类对象时应注意: 在外部类的内部可以直接使用inner s=new inner();(因为外部类知道inner是哪个类,所以可以生成对象。) 而在外部类的外部,要生成(new)一个内部类对象,需要首先建立一个外部类对象(外部类可用),然后在生成一个内部类对象。 Outer o=new Outer(); Outer.Inner in=o.new.Inner()。 package com.nyistdwp.staticClass; public class Main { public static void main(String[] args) { OuterClass oc = new OuterClass(); OuterClass.InnerClass ic = oc.new InnerClass(); System.out.println("访问外部类的data=" + oc.data); System.out.println("访问内部类的data2=" + ic.data2); ic.method(); } } package com.nyistdwp.staticClass; public class OuterClass { int data=5; class InnerClass{ int data2=10; void method() { System.out.println("data from OuterClass=" +data); System.out.println("data from innerClass="+data2); } } } 1.1.2. 静态内部类 (注意:前三种内部类与变量类似,所以可以对照参考变量) 静态内部类定义在类中,任何方法外,用static定义。 静态内部类只能访问外部类的静态成员。 生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成: Outer.Inner in=new Outer.Inner(); 而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类。静态内部类不可用private来进行定义。 注意:当类与接口(或者是接口与接口)发生方法命名冲突的时候,此时必须使用内部类来实现。 用接口不能完全地实现多继承,用接口配合内部类才能实现真正的多继承。 例子: 对于两个类,拥有相同的方法: class People { run(); } interface Machine{ run(); } 此时有一个robot类: class Robot extends People implement Machine. 此时run()不可直接实现。 interface Machine { void run(); } class Person { void run(){System.out.println("run");} } class Robot extends Person { private class MachineHeart implements Machine { public void run(){System.out.println("heart run");} } public void run(){System.out.println("Robot run");} Machine getMachine(){return new MachineHeart();} } class Test { public static void main(String[] args) { Robot robot=new Robot(); Machine m=robot.getMachine(); m.run(); robot.run(); } } package com.nyistdwp.RealStaticClass; /* * *静态内部类只能访问外部类的静态成员。 生成(new)一个静态内部类不需要外部类成员:这是静态内部类和成员内部类的区别。静态内部类的对象可以直接生成: Outer.Inner in=new Outer.Inner(); 而不需要通过生成外部类对象来生成。这样实际上使静态内部类成为了一个顶级类。静态内部类不可用private来进行定义 注意:当类与接口(或者是接口与接口)发生方法命名冲突的时候,此时必须使用内部类来实现。 用接口不能完全地实现多继承,用接口配合内部类才能实现真正的多继承。 */ public class Main { public static void main(String[] args) { OuterClass.InnerClass innerClass = new OuterClass.InnerClass(); System.out.println("data2=" + innerClass.data2); } } package com.nyistdwp.RealStaticClass; public class OuterClass { private void outMethod() { System.out.println("out method"); } private static void outStaticMethod() { int innerstaticVar=InnerClass.innerStaticVar;//外部类使用静态类部类的静态变量 System.out.println("this is outter static method"); } int data=5; static int staticData=10; static class InnerClass{ static int innerStaticVar=20; int data2=10; void method() { System.out.println("static data from OuterClass ="+staticData); System.out.println("data from innerClass="+data2); outStaticMethod();//可以访问外部非静态方法 } } } 1.1.3. 局部内部类 在方法中定义的内部类称为局部内部类。 与局部变量类似,在局部内部类前不加修饰符public和private,其范围为定义它的代码块。 注意: 局部内部类不仅可以访问外部类实例变量,也可以访问外部类的常量 在类外不可直接访问局部内部类(保证局部内部类对外是不可见的)。 在方法中才能调用其局部内部类。 package com.nyistdwp.LittleStaticClass; public class Main { public static void main(String[] args) { LocalInnerClass localInnerClass = new LocalInnerClass(); localInnerClass.m1(); } } package com.nyistdwp.LittleStaticClass; //局部内部类 public class LocalInnerClass { private int outer1; private static int outer2; public void m1() { String localVar; final String localVar2="zhangsan"; /* * 1.不允许使用private关键字 * private class InnerLocalClass * 2.不允许使用protected * protected class InnerLocalClass * */ class InnerLocalClass{ void m2(String arg){ System.out.println(arg); //3.不能访问外部局部变量 // System.out.println(localVar); //4.可以访问外部final局部变量 System.err.println(localVar2); //访问外部实例变量 System.out.println(outer1); //访问外部静态变量 System.out.println(outer2); } } InnerLocalClass innerLocalClass=new InnerLocalClass(); innerLocalClass.m2("test"); } } 1.1.4. 匿名内部类 匿名内部类是一种特殊的局部内部类,它是通过匿名类实现接口。 IA被定义为接口。 IA I=new IA(){}; 注:一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类,没有类名,根据多态,我们使用其父类名。 因其为局部内部类,那么局部内部类的所有限制都对其生效。 匿名内部类是唯一一种无构造方法类。 匿名内部类在编译的时候由系统自动起名Out$1.class。 如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。 因匿名内部类无构造方法,所以其使用范围非常的有限。 匿名内部类使用: 匿名内部类就是没有名字的内部类。什么情况下需要使用匿名内部类?如果满足下面的一些条件,使用匿名内部类是比较合适的: ?只用到类的一个实例。 ?类在定义后马上用到。 ?类非常小(SUN推荐是在4行代码以下) ?给类命名并不会导致你的代码更容易被理解。 在使用匿名内部类时,要记住以下几个原则: ?匿名内部类不能有构造方法。 ?匿名内部类不能定义任何静态成员、方法和类。 ?匿名内部类不能是public,protected,private,static。 ?只能创建匿名内部类的一个实例。 ?一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。 ?因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。 package com.nyistdwp.NonameStaticClass; public class Main { public static void main(String[] args) { // 匿名内部类 // 把接口匿名实现类赋给接口 TestInterface testInterface = new TestInterface() { @Override public void m2() { // TODO Auto-generated method stub } @Override public void m1() { // TODO Auto-generated method stub } }; // 通过接口变量调用方法 testInterface.m1(); testInterface.m2(); // 实现的匿名内部类实例赋给User User user = new User("zhangsan", 12) { @Override public void printInfo() { // 如果取消注释,那么匿名类无法继承父类User的私有变量 // System.out.println("{name="+name+",age="+age+"}"); System.out.println("my anonymouse method"); super.printInfo(); } public void newMethod() { System.out.println("new method in anonymouse"); } }; // 访问重载方法 user.printInfo(); // 无法访问子类的方法 // user.newMethod(); // 访问新定义的方法,只通过如下方法 new User("lisi", 32) { public void printInfo() { System.out.println("my anonymouse method 2"); } public void newMethod() { System.out.println("new method in anonymouse 2"); } }.newMethod(); AbstractShape shape = new AbstractShape() { @Override double area(int r) { return Math.PI * r * r; } }; System.out.println(shape.area(4)); double area = new AbstractShape() { @Override double area(int r) { // TODO Auto-generated method stub return Math.PI * r * r; } }.area(30); System.out.println(area); } } package com.nyistdwp.NonameStaticClass; public abstract class AbstractShape { abstract double area(int r); } package com.nyistdwp.NonameStaticClass; public interface TestInterface { public void m1(); public void m2(); } package com.nyistdwp.NonameStaticClass; public class User { private String name; private int age; public User(String name, int age) { super(); this.name = name; this.age = age; } public void printInfo(){ System.out.println("name="+name+",age="+age); } } 九.单例模式 1.概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。 单例模式有一下特点: 1、单例类只能有一个实例。 2、单例类必须自己创建自己的唯一实例。 3、单例类必须给所有其他对象提供这一实例。 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。 首先看一个经典的单例实现。 public class Singleton { private static Singleton uniqueInstance = null; private Singleton() { // Exists only to defeat instantiation. } public static Singleton getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueI; // Other methods... } Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。) 但是以上实现没有考虑线程安全问题。所谓线程安全是指:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。显然以上实现并不满足线程安全的要求,在并发环境下很可能出现多个Singleton实例。 public class TestStream { 2 private String name; 3 public String getName() { 4 return name; 5 } 6 public void setName(String name) { 7 this.name = name; 8 } 9 //该类只能有一个实例 10 private TestStream(){} //私有无参构造方法 11 //该类必须自行创建 12 //有2种方式 13 /*private static final TestStream ts=new TestStream();*/ 14 private static TestStream ts1=null; 15 //这个类必须自动向整个系统提供这个实例对象 16 public static TestStream getTest(){ 17 if(ts1==null){ 18 ts1=new TestStream(); 19 } 20 return ts1; 21 } 22 public void getInfo(){ 23 System.out.println("output message "+name); 24 } 25 } 1 public class TestMain { 2 public static void main(String [] args){ 3 TestStream s=TestStream.getTest(); 4 s.setName("张孝祥"); 5 System.out.println(s.getName()); 6 TestStream s1=TestStream.getTest(); 7 s1.setName("张孝祥"); 8 System.out.println(s1.getName()); 9 s.getInfo(); 10 s1.getInfo(); 11 if(s==s1){ 12 System.out.println("创建的是同一个实例"); 13 }else if(s!=s1){ 14 System.out.println("创建的不是同一个实例"); 15 }else{ 16 System.out.println("application error"); 17 } 18 } 19 } 运行结果: 张孝祥 张孝祥 output message 张孝祥 output message 张孝祥 创建的是同一个实例 结论:由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。 1.饿汉式单例类 1 //饿汉式单例类.在类初始化时,已经自行实例化 2 public class Singleton1 { 3 //私有的默认构造子 4 private Singleton1() {} 5 //已经自行实例化 6 private static final Singleton1 single = new Singleton1(); 7 //静态工厂方法 8 public static Singleton1 getInstance() { 9 return single; 10 } 11 } 2.懒汉式单例类 1 //懒汉式单例类.在第一次调用的时候实例化 2 public class Singleton2 { 3 //私有的默认构造子 4 private Singleton2() {} 5 //注意,这里没有final 6 private static Singleton2 single=null; 7 //静态工厂方法 8 public synchronized static Singleton2 getInstance() { 9 if (single == null) { 10 single = new Singleton2(); 11 } 12 return single; 13 } 14 } 3.登记式单例类 1 import java.util.HashMap; 2 import java.util.Map; 3 //登记式单例类. 4 //类似Spring里面的方法,将类名注册,下次从里面直接获取。 5 public class Singleton3 { 6 private static Map<String,Singleton3> map = new HashMap<String,Singleton3>(); 7 static{ 8 Singleton3 single = new Singleton3(); 9 map.put(single.getClass().getName(), single); 10 } 11 //保护的默认构造子 12 protected Singleton3(){} 13 //静态工厂方法,返还此类惟一的实例 14 public static Singleton3 getInstance(String name) { 15 if(name == null) { 16 name = Singleton3.class.getName(); 17 System.out.println("name == null"+"--->name="+name); 18 } 19 if(map.get(name) == null) { 20 try { 21 map.put(name, (Singleton3) Class.forName(name).newInstance()); 22 } catch (InstantiationException e) { 23 e.printStackTrace(); 24 } catch (IllegalAccessException e) { 25 e.printStackTrace(); 26 } catch (ClassNotFoundException e) { 27 e.printStackTrace(); 28 } 29 } 30 return map.get(name); 31 } 32 //一个示意性的商业方法 33 public String about() { 34 return "Hello, I am RegSingleton."; 35 } 36 public static void main(String[] args) { 37 Singleton3 single3 = Singleton3.getInstance(null); 38 System.out.println(single3.about()); 39 } 40 }
原文:http://www.cnblogs.com/yu0312chao/p/3738207.html