If you pass in the list of possible values, then you can do it without so much as depending upon the type being an enum. 
public static <T> T findByString(T[] values, String toString) {
    Objects.requireNonNull(toString);
    for (T t : values) {
        if (toString.equals(t.toString())) {
            return t;
        }
    }
    throw new IllegalArgumentException();
}
Call with:
Blah blah = SomeClass.findByString(Blah.values(), str);
Rather than calling Blah.values() every time, you could use put it in an object, which could be passed around and used generically. Perhaps other methods added later.
public interface ByString<T> { // Choose a better name.
    T find(String toString);
}
[...]
    private static final ByString<Blah> blahs = byString(Blah.values());
[...]
    public static <T> ByString<T> byString(T[] values) {
        final T[] valuesCopy = values.clone();
        return new ByString<T>() {
            public T find(String toString) {
                return SomeClass.findByString(valuesCopy, toString);
            }
        };
    }
[...]
Call with:
Blah blah = blahs.find(str);
In fact, you might want to optimise that. Do the toStringing once, and use a map.
    public static <T> ByString<T> byString(T[] values) {
        final Map<String,T> byToStrings = new HashMap<>(
            (int)(values.length/0.75f)+1 // Doesn't HashMap construction suck.
        );
        for (T value : values) {
            byToStrings.put(values.toString(), value);
        }
        return new ByString<T>() {
            public T find(String toString) {
                T value = byToStrings.get(toString);
                if (value == null) {
                    throw new IllegalArgumentException();
                }
                return value;
            }
        };
    }