Java-001-枚举、反射、类加载器、内省、注解、泛型、代理

Java基础总结

以下笔记整理自张孝祥老师的《Java高新技术》视频教程

01 枚举

public class EnumTest {
    public static void main(String[] args) {
        WeekDay weekDay2 = WeekDay.FRI;
        System.out.println(weekDay2);
        System.out.println(weekDay2.name());
        System.out.println(weekDay2.ordinal());    //排序从零开始
        System.out.println(WeekDay.valueOf("SUN").toString());
        System.out.println(WeekDay.values().length);
        
        new Date(300){//覆写父类方法};
    }

    public enum WeekDay{
        SUN(1),MON(),TUE,WED,THI,FRI,SAT;
        private WeekDay(){System.out.println("first");}
        private WeekDay(int day){System.out.println("second");}
    }
    
    public enum TrafficLamp{
        //每个成员都是TrafficLamp的对象
        RED(30){//子类对象,调用有参构造方法,覆写父类方法
            public  TrafficLamp nextLamp(){
                return GREEN;
            }
        },
        GREEN(45){
            public  TrafficLamp nextLamp(){
                return YELLOW;
            }            
        },
        YELLOW(5){
            public  TrafficLamp nextLamp(){
                return RED;
            }            
        };
        public abstract TrafficLamp nextLamp();
        private int time;
        private TrafficLamp(int time){this.time = time;}
    }
}

02 反射

反射就是把Java类中的各种成分映射成相应的Java类

注意:反射Constructor、Field:

  1. ∵方法和属性都是对象的,∴要得到属性值、更改属性值、调用用方法是要传入具体的对象
  2. 调用静态方法时对象传入null即可

反射获取泛型参数类型

public class GenericTest {
    public static void main(String[] args) throws Exception {
        ...
        //Vector<Date> v1 = new Vector<Date>();
        Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
        Type[] types = applyMethod.getGenericParameterTypes();    //以泛型方式得到每个参数的类型
        ParameterizedType pType = (ParameterizedType)types[0];    //第一个参数的类型
        System.out.println(pType.getRawType());                    //原始类型 :Vector
        System.out.println(pType.getActualTypeArguments()[0]);    //实际类型参数:Date
    }
    
    public static void applyVector(Vector<Date> v1){        
    }
}

获取父类泛型的实际参数类型

public abstract class DaoSupportImpl<T> implements DaoSupport<T> {
    private Class<T> clazz;
    public DaoSupportImpl() {
        // 得到T的真实类型
        // this表示当前new的对象实例.
        // getGenericSuperclass()表示获取对象的泛型的父类的类型信息;即DaoSupport<T>
        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
        this.clazz = (Class) pt.getActualTypeArguments()[0]; // 获取真实类型信息
        System.out.println("-----> clazz = " + clazz);
    }
}

得到类的字节码对象 Class

注意:
用类来得到Class,用.class
用对象来得到Class,用getClass()方法
用完整类名来得到Class,用Class.forName(“...”);

Person p = new Person();

  1. Class c1 = Person.class [1]
  2. Class c2 = p.getClass() //用对象来得到Class
  3. Class c3 = Class.forName(“com.ttino.model.Person”);
  4. Android中的方法,仅参考
private void getCacheSize(PackageInfo packageInfo) {
    try {
        Class<?> clazz = getClassLoader().loadClass("packageManager");
        //通过反射获取到当前的方法
        Method method = clazz.getDeclaredMethod("getPackageSizeInfo", 
                            String.class,IPackageStatsObserver.class);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

有9个预定义的Class对象 :8个基本类型 + void (void.class)
**int.class.isPrimitive(); ** //true;是否是原始(基本)类型 的字节码
**int[].class.isArray(); ** //true; 判断Class是否是数组

java四类八种基本数据类型:

第一类:整型 byte short int long
第二类:浮点型 float double
第三类:逻辑型 boolean(它只有两个值可取true false)
第四类:字符型 char

反射构造方法Constructor

反射字段Filed

/**
 * 将一个对象中的所有String类型的成员变量所对应的字符串内容中的"b"改成"a"
 */
Object obj = Class.forName("...").newInstance();
Field[] fields = obj.getClass().getDeclaredFields();
for(Field f : fields){
    if(f.getType() == String.class){ //字节码用==来比较,因为只有一份
        f.setAccessible(true);
        String newValue = ((String)f.get(obj)).replace('b', 'a');
        f.set(obj, newValue);    
    }
}
System.out.println(obj);//覆写了obj的toString()方法

反射方法Method

//兼容jdk1.4,在1.5中的写法
//方法一:让1.5编译器去拆,拆除来的就是Object
//mainMethod.invoke(null, new Object[]{new String[]{"111","222","333"}});
//方法二:告诉1.5的编译器不要拆
mainMethod.invoke(null, (Object)new String[]{"111","222","333"});

数组反射

维度和类型都相同的数组,class是同一种类型

数组和Object的对应关系:

int [] a1 = new int[]{1,2,3};
int [] a2 = new int[4];
int[][] a3 = new int[2][3];
String [] a4 = new String[]{"a","b","c"};

Object aObj1 = a1;
Object aObj2 = a4;
//Object[] aObj3 = a1;//a1数组里装的是int, int(基本类型)不是Object, Integer(对象包装类)是
Object[] aObj4 = a3;//数组里装的是数组,数组的父类是Object[a1.getClass().getSuperclass().getName()]
Object[] aObj5 = a4;//数组里装的是String,String是Object

打印数组里的内容:
//整数不会转为List中的元素
System.out.println(Arrays.asList(a1));//[[I@4e25154f]
System.out.println(Arrays.asList(a4));//[a, b, c] //String转了

asList(T...a) //1.5 // List<String> stooges = 
                        Arrays.asList("Larry", "Moe", "Curly");
asList(Object[] o)//1.4

反射数组的长度和内容,用Array类

private static void printObject(Object obj) {
    Class clazz = obj.getClass();
    if(clazz.isArray()){
        int len = Array.getLength(obj);//长度
        for(int i=0;i<len;i++){
            System.out.println(Array.get(obj, i));//内容
        }
    }else{//如果不是数组,直接打印
        System.out.println(obj);
    }    
}

03 框架与工具类

  1. 开发商卖给你房子,你装上自己的门,买了把锁

框架:开发商提供的房子,可以卖给任何人
自己的类:门看成是自己的做的,用户将门装在房子中
工具类:锁看成是买的别人的,锁被门调用

  1. 框架调用用户提供的类,工具类被用户调用

04 类加载器

  1. 最直接的方式
InputStream ips = new FileInputStream("config.properties");
  1. 用Class得到类加载器getClassLoader().getResourceAsStream。默认从classpath(编译好的.class文件的存放路径)根目录下查找文件
    注意:路径前面不加/
InputStream ips = ReflectTest2.class.getClassLoader().getResourceAsStream("cn/itcast/day1/config.properties");
  1. 直接用Class的getResourceAsStream()
  • 3.1、如果不用/开头,默认从ReflectTest2.class所在目录下开始查找 [相对路径]
InputStream ips = ReflectTest2.class.getResourceAsStream("config.properties");
  • 3.2、如果用/开头,绝对路径查找
InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");

4.示例

InputStream ips = ReflectTest2.class.getResourceAsStream("/cn/itcast/day1/resources/config.properties");
Properties props = new Properties();
props.load(ips);
//这里释放的是对象关联的系统资源,不是对象本省,ips对象由JVM管理
ips.close();//释放对象关联的系统资源,否则会有内存泄露
String className = props.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();

05 内省(Introspector)操作JavaBean

//ReflectPoint pt1 = new ReflectPoint(3,5); //JavaBean    
//String propertyName = "x";
//getProperty(pt1, propertyName);

private static Object getProperty(Object pt1, String propertyName)throws Exception {
    /*
    //方式一
PropertyDescriptor pd = new PropertyDescriptor(propertyName, pt1.getClass());//传入属性名和Class
    Method methodGetX = pd.getReadMethod();
    Object retVal = methodGetX.invoke(pt1);
*/
    
    //方式二
    BeanInfo beanInfo =  Introspector.getBeanInfo(pt1.getClass());
    PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
    Object retVal = null;
    for(PropertyDescriptor pd : pds){
        if(pd.getName().equals(propertyName)) {
            Method methodGetX = pd.getReadMethod();
            retVal = methodGetX.invoke(pt1);
            break;
        }
    }
    return retVal;
}

06 BeanUtils操作JavaBean

copyProperties():将一个对象的属性复制到另一对象
descirble():将JavaBean转为map
populate():将map的内容填充到JavaBean

ReflectPoint pt1 = new ReflectPoint(3,5);
//BeanUtils set时会以String类型来set;get时会以String类型来返回
//参数:对象、属性名
BeanUtils.getProperty(pt1, "x").getClass().getName();//java.lang.String;实际上x是int型
//参数:队形、属性名,值
BeanUtils.setProperty(pt1, "x", "9");
/*
//java7的新特性
Map map = {name:"zxx",age:18};
BeanUtils.setProperty(map, "name", "lhm");
*/
//级联属性
BeanUtils.setProperty(pt1, "birthday.time", "111");
System.out.println(BeanUtils.getProperty(pt1, "birthday.time"));

//PropertyUtils操作JavaBean        
//操作时,注意类型要与属性字段的类型对应
PropertyUtils.setProperty(pt1, "x", 9);
System.out.println(PropertyUtils.getProperty(pt1, "x").getClass().getName());//java.lang.Integer

07 注解

@SuppressWarnings(“deprecation”):取消警告 //source阶段,编译器用完了(编译成.class)就没用了
@Deprcation:过时 //runtime阶段,编译器是通过读类二进制来检查某个方法是否过期
@Override:覆写 //source阶段

注解应用:3个类
注解类 + 应用了“注解类”的类 + 对‘应用了“注解类”的类’进行反射操作的类

//SOURCE、CLASS、RUNTIME分别对应的注解生命周期:java源文件class文件内存中的字节码。默认CLASS
@Retention(RententionPolicy.RUNTIME)//保留到运行期间[元注解];或(value=”RUNTIME”)
//@Target({ElementType.METHOD,ElementType.TYPE}) //只能放在方法和类型上
public @interface ItcastAnnotation    {}

元注解:为注解服务的注解
元数据:数据的数据
原信息:信息的信息

注解类:

EnumTest类参考枚举
ItcastAnnotaion.java

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface ItcastAnnotation {
    String color() default "blue";
    String value();
    int[] arrayAttr() default {3,4,4};
    EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;
    MetaAnnotation annotationAttr() default @MetaAnnotation("lhm");
}

MetaAnnotaion.java
public @interface MetaAnnotation {
    String value();
}

应用了“注解类”的类,其中Main方法暂作为“对注解进行解析”的代码存放处

@ItcastAnnotation(annotationAttr=@MetaAnnotation("flx"),color="red",value="abc",arrayAttr=1)
public class AnnotationTest {
    @SuppressWarnings("deprecation")
    @ItcastAnnotation("xyz")
    public static void main(String[] args) throws Exception{
         System.runFinalizersOnExit(true);//测试@suppressWarnings注解
         //如果AnnotionTest类上存在ItcastAnnotation注解
        if(AnnotationTest.class.isAnnotationPresent(ItcastAnnotation.class)){
            ItcastAnnotation annotation = (ItcastAnnotation)AnnotationTest.class.getAnnotation(ItcastAnnotation.class);
            System.out.println(annotation.color());//red
            System.out.println(annotation.value());//abc
            System.out.println(annotation.arrayAttr().length);//1
            System.out.println(annotation.lamp().nextLamp().name());//GREEN
            System.out.println(annotation.annotationAttr().value());//flx
        }

        //获取Main方法上的注解
        Method mainMethod = AnnotationTest.class.getMethod("main", String[].class);
        ItcastAnnotation annotation2 = (ItcastAnnotation)mainMethod.getAnnotation(ItcastAnnotation.class);
        System.out.println(annotation2.value());//xyz
    }
}

08 泛型

泛型是给编译器看的,编译完后不保存泛型的类型

  1. 整个ArrayList<E> 称为泛型类型
  2. ArrayList<E>中的E 称为类型变量或类型参数
  3. 整个ArrayList<Integer> 称为参数化的类型
  4. ArrayList<Integer>中的Integer 称为类型参数的实例或实际类型参数
  5. ArrayList<Integer>中的<> 念typeof
  6. ArrayList 称为原始类型

泛型中的通配符:
?:任意类型

自定义泛型:

1 方法:

1.1、自定义类型T要在返回类型前、紧挨着返回类型声明
1.2、返回类型T推断:取最小公倍数;如果有返回类型,优先考虑返回类型

copy(new Date[], new String[10]);
<T> void copy(T dest, T[] src){} 

类型推断有时要考虑<>中的类型传递:

copy(new Vector<String>[], new String[10]);//copy(new Vector<Date>[], new String[10]):错误
<T> void copy(Collection<T> col, T[] arr){} 

1.3、泛型T的实际类型只能是引用类型,不能是基本数据类型

private static <T> T add<T x, T y){
    return null;
}

限定T

private static <T extends Serializable&Number> T sub(Class<T> clazz){}

泛型异常

private static <T extends Exception > void Say() throws T{
    try{}catch(Exception e){throw (T)e}
}

2.类

dao:data access object,数据访问对象
类里面的静态成员不能使用泛型对象

public class GenericDao<T>{
}

09 类加载器

  • BootStrap:jre/lib/rt.jar
    • |-ExtClassLoader:jre/lib/ext/*.jar
      • |-AppClassLoader:classpath下指定的所有jar或目录
        • |-MyClassLoader:自定义的特殊目录

Thread指定类加载器:
ClassLoader getContextClassLoader() 返回该线程的上下文 ClassLoader
void setContextClassLoader(ClassLoader cl) 设置该线程的上下文 ClassLoader

自定义的类加载器加载指定的类:
ClassLoader.loadClass()

类加载器委托加载机制:
父加载器加载 -> 子加载器加载

自定义类加载器

原始类:

public class ClassLoaderAttachment extends Date {
    public String toString(){
        return "hello,itcast";
    } 
}

调用类:

public static void main(String[] args) throws Exception {
    //加载.class文件
    Class clazz = new MyClassLoader("itcastlib").loadClass("cn.itcast.day2.ClassLoaderAttachment");
    Date d1 =  (Date)clazz.newInstance();
    System.out.println(d1);
}

加载器:

public class MyClassLoader extends ClassLoader{
    //测试加解密
    public static void main(String[] args) throws Exception {
        String srcPath = args[0];
        String destDir = args[1];
        FileInputStream fis = new FileInputStream(srcPath);
        String destFileName = srcPath.substring(srcPath.lastIndexOf('\\')+1);
        String destPath = destDir + "\\" + destFileName;
        FileOutputStream fos = new FileOutputStream(destPath);
        cypher(fis,fos);
        fis.close();
        fos.close();
    }
    //加密方法
    private static void cypher(InputStream ips ,OutputStream ops) throws Exception{
        int b = -1;
        while((b=ips.read())!=-1){
            ops.write(b ^ 0xff);
        }
    }

//-------------------功能分割线------------------------
    //class文件的目录
    private String classDir;

    //查找Class
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //文件全名 = 目录 + \ + 名称 + .class
        String classFileName = classDir + "\\"  + name.substring(name.lastIndexOf('.')+1) + ".class";
        try {
            FileInputStream fis = new FileInputStream(classFileName);
            ByteArrayOutputStream  bos = new ByteArrayOutputStream();
            cypher(fis,bos);
            fis.close();
            byte[] bytes = bos.toByteArray();
            return defineClass(bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public MyClassLoader(){
    }
    public MyClassLoader(String classDir){
        this.classDir = classDir;
    }
}

10 代理的概念与作用

JVM代理
三个参数:1、类加载器;2、接口;3、InvocationHandler

Proxy生成的代理类继承了Object的方法:
其中只有hashCode、equals、toString三个方法才交给invocationHandler的invoke去处理,其它方法都有自己的实现

1、分步获取

获取代理类 -> 获取代理类的构造方法 -> 构造方法中传入InvocationHandler来创建实例对象

public class ProxyTest {
    public static void main(String[] args) throws Exception{
        //0、创建Collection接口的代理类
        //参数1:类加载器;参数2:接口
        Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
        //1、打印代理类的名称
        System.out.println(clazzProxy1.getName());
        
        //2、获取代理类的所有构造方法
        System.out.println("----------begin constructors list----------");
        Constructor[] constructors = clazzProxy1.getConstructors();
        for(Constructor constructor : constructors){
            String name = constructor.getName();
            StringBuilder sBuilder = new StringBuilder(name);
            sBuilder.append('(');
            Class[] clazzParams = constructor.getParameterTypes();
            for(Class clazzParam : clazzParams){
                sBuilder.append(clazzParam.getName()).append(',');
            }
            if(clazzParams!=null && clazzParams.length != 0)
                sBuilder.deleteCharAt(sBuilder.length()-1);
            sBuilder.append(')');
            System.out.println(sBuilder.toString());            
        }

        //3、获取代理类的所有方法
        System.out.println("----------begin methods list----------");
        Method[] methods = clazzProxy1.getMethods();
        for(Method method : methods){
            String name = method.getName();
            StringBuilder sBuilder = new StringBuilder(name);
            sBuilder.append('(');
            Class[] clazzParams = method.getParameterTypes();
            for(Class clazzParam : clazzParams){
                sBuilder.append(clazzParam.getName()).append(',');
            }
            if(clazzParams!=null && clazzParams.length != 0)
                sBuilder.deleteCharAt(sBuilder.length()-1);
            sBuilder.append(')');
            System.out.println(sBuilder.toString());            
        }
        
        //4、创建代理类的实例
        System.out.println("----------begin create instance object----------");
        //Object obj = clazzProxy1.newInstance();//错误,代理类中没有不带参数的构造方法
        //4.1、获取唯一的构造方法
        Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
        
        //自定义InvocationHandler类
        class MyInvocationHander1 implements InvocationHandler{
            //参数1:代理对象、参数2:代理对象的某个方法、参数3:方法接受的参数
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        }
        Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());
        System.out.println(proxy1.toString());
        proxy1.clear();
        //proxy1.size(); //invoke返回null,size()要的是整数,null不能转成整数,所以报错

        Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return null;
            }
        });
    }
}

2、一步到位

Collection proxy3 = (Collection) Proxy.newProxyInstance(
        Collection.class.getClassLoader(),    // 参数1:ClassLoader
        new Class[] { Collection.class },    // 参数2:Class[]
        new InvocationHandler() {             // 参数3:InvocationHandler
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                ArrayList target = new ArrayList();
                 return method.invoke(target, args);
            }
});

proxy3.add("111"); Syso(proxy3.size());//0
//原因:每调用一次方法都会去调用InvocationHandler的invoke方法,而每一次都会new一个ArrayList
//可以把ArrayList改成InvoketionHandler的成员变量

3、AOP原理

public class ProxyTest {
    public static void main(String[] args) throws Exception{
        final ArrayList target = new ArrayList();            
        Collection proxy3 = (Collection)getProxy(target,new MyAdvice());
        proxy3.add("zxx");
        proxy3.add("lhm");
        proxy3.add("bxd");
        System.out.println(proxy3.size());
        System.out.println(proxy3.getClass().getName());
    }

    private static Object getProxy(final Object target,final Advice advice) {
        Object proxy3 = Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler(){
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        advice.beforeMethod(method);
                        Object retVal = method.invoke(target, args);
                        advice.afterMethod(method);
                        return retVal;                                                
                    }
                });
        return proxy3;
    }
}



public class MyAdvice implements Advice {
    long beginTime = 0;
    public void afterMethod(Method method) {
        System.out.println("从传智播客毕业上班啦!");        
        long endTime = System.currentTimeMillis();
        System.out.println(method.getName() + " running time of " + (endTime - beginTime));

    }

    public void beforeMethod(Method method) {
        System.out.println("到传智播客来学习啦!");
        beginTime = System.currentTimeMillis();
    }
}



public interface Advice {
    void beforeMethod(Method method);
    void afterMethod(Method method);
}

4、Spring的Bean工厂模拟

1、BeanFactory.java

public class BeanFactory {
    //加载配置文件
    Properties props = new Properties();
    public BeanFactory(InputStream ips){
        try {
            props.load(ips);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //创建Bean
    public Object getBean(String name){//传入name,对象配置文件的xxx
        String className = props.getProperty(name);
        Object bean = null;
        try {//创建JavaBean
            Class clazz = Class.forName(className);
            bean = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        } 
        
        //如果bean是ProxyFactoryBean,创建代理对象
        if(bean instanceof ProxyFactoryBean){
            Object proxy = null;
            //由ProxyFactoryBean来创建代理对象
            ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean;
            try {
                Advice advice = (Advice)Class.forName(props.getProperty(name + ".advice")).newInstance();
                Object target = Class.forName(props.getProperty(name + ".target")).newInstance();
                proxyFactoryBean.setAdvice(advice);
                proxyFactoryBean.setTarget(target);
                proxy = proxyFactoryBean.getProxy();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return proxy;
        }
        return bean;
    }
}

2、ProxyFactoryBean.java

public class ProxyFactoryBean {
    private Advice advice;
    private Object target;

    ... get和set方法

    public Object getProxy() {
        Object proxy3 = Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                /*new Class[]{Collection.class},*/
                target.getClass().getInterfaces(),
                new InvocationHandler(){
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        advice.beforeMethod(method);
                        Object retVal = method.invoke(target, args);
                        advice.afterMethod(method);
                        return retVal;                        
                    }
                });
        return proxy3;
    }
}

3、config.properties

#xxx=java.util.ArrayList
xxx=cn.itcast.day3.aopframework.ProxyFactoryBean
xxx.advice=cn.itcast.day3.MyAdvice
xxx.target=java.util.ArrayList

4、测试类:

public class AopFrameworkTest {
    public static void main(String[] args) throws Exception {
        InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
        Object bean = new BeanFactory(ips).getBean("xxx");
        System.out.println(bean.getClass().getName());
        ((Collection)bean).clear();
    }
}

  1. 作用:返回字节码对象。如果字节码之前被加载过,已存在JVM中,则直接返回...;如果没有,则先用类加载器加载,将加载的字节码保存到JVM中,然后返回...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 在经过一次没有准备的面试后,发现自己虽然写了两年的android代码,基础知识却忘的差不多了。这是程序员的大忌,没...
    猿来如痴阅读 2,827评论 3 10
  • 整体Retrofit内容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李头阅读 4,554评论 2 12
  • 红卫小学小叮当教育五年级黄语妍 一天,我正写作文,我把笔拿在手中旋转,想不出要写什么,就在这时笔掉在了地...
    佳韵作文向老师阅读 220评论 0 0
  • 那天下午我们在库房练琴,和往常一样讨论琴技、吃东西,神侃。不知是谁把话题扯到大学无聊的生活来,大家都有感而发,气氛...
    读破书万卷阅读 175评论 0 0
  • 在与朋友们的闲聊中,他们总是不会忘记对你表达一番真诚地艳羡,说,作为老师真幸福,马上有漫长的两个月的暑假等着你,想...
    坐忘mao阅读 274评论 0 0